Merge pull request #635 from NapNeko/ref/ob-network

refactor: adjust onebot network
This commit is contained in:
手瓜一十雪
2024-12-17 09:07:39 +08:00
committed by GitHub
10 changed files with 106 additions and 107 deletions

View File

@@ -38,6 +38,14 @@ export interface AdapterConfig extends AdapterConfigInner {
const createDefaultAdapterConfig = <T extends AdapterConfig>(config: T): T => config; const createDefaultAdapterConfig = <T extends AdapterConfig>(config: T): T => config;
export interface PluginConfig extends AdapterConfig {
name: string;
enable: boolean;
messagePostFormat: string;
reportSelfMessage: boolean;
debug: boolean;
}
export const httpServerDefaultConfigs = createDefaultAdapterConfig({ export const httpServerDefaultConfigs = createDefaultAdapterConfig({
name: 'http-server', name: 'http-server',
enable: false as boolean, enable: false as boolean,
@@ -128,7 +136,7 @@ export const mergeNetworkDefaultConfig = {
websocketClients: websocketClientDefaultConfigs, websocketClients: websocketClientDefaultConfigs,
} as const; } as const;
export type NetworkConfigAdapter = HttpServerConfig | HttpClientConfig | WebsocketServerConfig | WebsocketClientConfig | AdapterConfig; export type NetworkConfigAdapter = HttpServerConfig | HttpClientConfig | WebsocketServerConfig | WebsocketClientConfig | PluginConfig;
type NetworkConfigKeys = keyof typeof mergeNetworkDefaultConfig; type NetworkConfigKeys = keyof typeof mergeNetworkDefaultConfig;
export function mergeOneBotConfigs( export function mergeOneBotConfigs(
@@ -234,4 +242,4 @@ export function getConfigBoolKey(
} }
}); });
return result; return result;
} }

View File

@@ -16,7 +16,6 @@ import {
} from '@/core'; } from '@/core';
import { OB11ConfigLoader } from '@/onebot/config'; import { OB11ConfigLoader } from '@/onebot/config';
import { import {
IOB11NetworkAdapter,
OB11ActiveHttpAdapter, OB11ActiveHttpAdapter,
OB11ActiveWebSocketAdapter, OB11ActiveWebSocketAdapter,
OB11NetworkManager, OB11NetworkManager,
@@ -44,9 +43,16 @@ import { OB11GroupRecallNoticeEvent } from '@/onebot/event/notice/OB11GroupRecal
import { LRUCache } from '@/common/lru-cache'; import { LRUCache } from '@/common/lru-cache';
import { NodeIKernelRecentContactListener } from '@/core/listeners/NodeIKernelRecentContactListener'; import { NodeIKernelRecentContactListener } from '@/core/listeners/NodeIKernelRecentContactListener';
import { BotOfflineEvent } from './event/notice/BotOfflineEvent'; import { BotOfflineEvent } from './event/notice/BotOfflineEvent';
import { AdapterConfigWrap, mergeOneBotConfigs, migrateOneBotConfigsV1, NetworkConfigAdapter, OneBotConfig } from './config/config'; import {
AdapterConfigWrap,
mergeOneBotConfigs,
migrateOneBotConfigsV1,
NetworkConfigAdapter,
OneBotConfig,
} from './config/config';
import { OB11Message } from './types'; import { OB11Message } from './types';
import { OB11PluginAdapter } from './network/plugin'; import { OB11PluginAdapter } from './network/plugin';
import { IOB11NetworkAdapter } from "@/onebot/network/adapter";
//OneBot实现类 //OneBot实现类
export class NapCatOneBot11Adapter { export class NapCatOneBot11Adapter {
@@ -110,12 +116,12 @@ export class NapCatOneBot11Adapter {
// 注册Plugin 如果需要基于NapCat进行快速开发 // 注册Plugin 如果需要基于NapCat进行快速开发
// this.networkManager.registerAdapter( // this.networkManager.registerAdapter(
// new OB11PluginAdapter('plugin', this.core, this,this.actions) // new OB11PluginAdapter('myPlugin', this.core, this,this.actions)
// ); // );
for (const key of ob11Config.network.httpServers) { for (const key of ob11Config.network.httpServers) {
if (key.enable) { if (key.enable) {
this.networkManager.registerAdapter( this.networkManager.registerAdapter(
new OB11PassiveHttpAdapter(key.name, key, this.core, this.actions) new OB11PassiveHttpAdapter(key.name, key, this.core, this, this.actions)
); );
} }
} }
@@ -133,6 +139,7 @@ export class NapCatOneBot11Adapter {
key.name, key.name,
key, key,
this.core, this.core,
this,
this.actions this.actions
) )
); );
@@ -145,6 +152,7 @@ export class NapCatOneBot11Adapter {
key.name, key.name,
key, key,
this.core, this.core,
this,
this.actions this.actions
) )
); );
@@ -191,10 +199,12 @@ export class NapCatOneBot11Adapter {
await this.handleConfigChange(prev.network.websocketClients, now.network.websocketClients, OB11ActiveWebSocketAdapter); await this.handleConfigChange(prev.network.websocketClients, now.network.websocketClients, OB11ActiveWebSocketAdapter);
} }
private async handleConfigChange( private async handleConfigChange<CT extends NetworkConfigAdapter>(
prevConfig: NetworkConfigAdapter[], prevConfig: NetworkConfigAdapter[],
nowConfig: NetworkConfigAdapter[], nowConfig: NetworkConfigAdapter[],
adapterClass: new (...args: any[]) => IOB11NetworkAdapter adapterClass: new (
...args: ConstructorParameters<typeof IOB11NetworkAdapter<CT>>
) => IOB11NetworkAdapter<CT>
): Promise<void> { ): Promise<void> {
// 比较旧的在新的找不到的回收 // 比较旧的在新的找不到的回收
for (const adapterConfig of prevConfig) { for (const adapterConfig of prevConfig) {
@@ -215,12 +225,7 @@ export class NapCatOneBot11Adapter {
await this.networkManager.closeSomeAdaterWhenOpen([existingAdapter]); await this.networkManager.closeSomeAdaterWhenOpen([existingAdapter]);
} }
} else if (adapterConfig.enable) { } else if (adapterConfig.enable) {
let newAdapter = new adapterClass( adapterConfig.name, adapterConfig, this.core, this.actions ); const newAdapter = new adapterClass(adapterConfig.name, adapterConfig as CT, this.core, this, this.actions);
if (adapterClass === OB11ActiveHttpAdapter) {
newAdapter = new adapterClass(adapterConfig.name, adapterConfig, this.core, this, this.actions);
}
await this.networkManager.registerAdapterAndOpen(newAdapter); await this.networkManager.registerAdapterAndOpen(newAdapter);
} }
} }

View File

@@ -1,27 +1,18 @@
import { IOB11NetworkAdapter, OB11EmitEventContent, OB11NetworkReloadType } from '@/onebot/network/index'; import { OB11EmitEventContent, OB11NetworkReloadType } from '@/onebot/network/index';
import { createHmac } from 'crypto'; import { createHmac } from 'crypto';
import { LogWrapper } from '@/common/log';
import { QuickAction, QuickActionEvent } from '@/onebot/types'; import { QuickAction, QuickActionEvent } from '@/onebot/types';
import { NapCatCore } from '@/core'; import { NapCatCore } from '@/core';
import { NapCatOneBot11Adapter } from '..'; import { NapCatOneBot11Adapter } from '..';
import { RequestUtil } from '@/common/request'; import { RequestUtil } from '@/common/request';
import { HttpClientConfig } from '@/onebot/config/config'; import { HttpClientConfig } from '@/onebot/config/config';
import { ActionMap } from '@/onebot/action'; import { ActionMap } from '@/onebot/action';
import { IOB11NetworkAdapter } from "@/onebot/network/adapter";
export class OB11ActiveHttpAdapter implements IOB11NetworkAdapter { export class OB11ActiveHttpAdapter extends IOB11NetworkAdapter<HttpClientConfig> {
logger: LogWrapper;
isEnable: boolean = false;
config: HttpClientConfig;
constructor( constructor(
public name: string, name: string, config: HttpClientConfig, core: NapCatCore, obContext: NapCatOneBot11Adapter, actions: ActionMap
config: HttpClientConfig,
public core: NapCatCore,
public obContext: NapCatOneBot11Adapter,
public actions: ActionMap,
) { ) {
this.logger = core.context.logger; super(name, config, core, obContext, actions);
this.config = structuredClone(config);
} }
onEvent<T extends OB11EmitEventContent>(event: T) { onEvent<T extends OB11EmitEventContent>(event: T) {

View File

@@ -1,29 +1,21 @@
import { IOB11NetworkAdapter, OB11EmitEventContent, OB11NetworkReloadType } from '@/onebot/network/index'; import { OB11EmitEventContent, OB11NetworkReloadType } from '@/onebot/network/index';
import { WebSocket } from 'ws'; import { WebSocket } from 'ws';
import { OB11HeartbeatEvent } from '@/onebot/event/meta/OB11HeartbeatEvent'; import { OB11HeartbeatEvent } from '@/onebot/event/meta/OB11HeartbeatEvent';
import { NapCatCore } from '@/core'; import { NapCatCore } from '@/core';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { OB11Response } from '@/onebot/action/OneBotAction'; import { OB11Response } from '@/onebot/action/OneBotAction';
import { LogWrapper } from '@/common/log';
import { ActionMap } from '@/onebot/action'; import { ActionMap } from '@/onebot/action';
import { LifeCycleSubType, OB11LifeCycleEvent } from '@/onebot/event/meta/OB11LifeCycleEvent'; import { LifeCycleSubType, OB11LifeCycleEvent } from '@/onebot/event/meta/OB11LifeCycleEvent';
import { WebsocketClientConfig } from '@/onebot/config/config'; import { WebsocketClientConfig } from '@/onebot/config/config';
import { NapCatOneBot11Adapter } from "@/onebot";
import { IOB11NetworkAdapter } from "@/onebot/network/adapter";
export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter { export class OB11ActiveWebSocketAdapter extends IOB11NetworkAdapter<WebsocketClientConfig> {
isEnable: boolean = false;
logger: LogWrapper;
private connection: WebSocket | null = null; private connection: WebSocket | null = null;
private heartbeatRef: NodeJS.Timeout | null = null; private heartbeatRef: NodeJS.Timeout | null = null;
public config: WebsocketClientConfig;
constructor( constructor(name: string, config: WebsocketClientConfig, core: NapCatCore, obContext: NapCatOneBot11Adapter, actions: ActionMap) {
public name: string, super(name, config, core, obContext, actions);
confg: WebsocketClientConfig,
public core: NapCatCore,
public actions: ActionMap,
) {
this.logger = core.context.logger;
this.config = structuredClone(confg);
} }
onEvent<T extends OB11EmitEventContent>(event: T) { onEvent<T extends OB11EmitEventContent>(event: T) {

View File

@@ -0,0 +1,33 @@
import { NetworkConfigAdapter } from "@/onebot/config/config";
import { LogWrapper } from "@/common/log";
import { NapCatCore } from "@/core";
import { NapCatOneBot11Adapter } from "@/onebot";
import { ActionMap } from "@/onebot/action";
import { OB11EmitEventContent, OB11NetworkReloadType } from "@/onebot/network/index";
export abstract class IOB11NetworkAdapter<CT extends NetworkConfigAdapter> {
name: string;
isEnable: boolean = false;
config: CT;
readonly logger: LogWrapper;
readonly core: NapCatCore;
readonly obContext: NapCatOneBot11Adapter;
readonly actions: ActionMap;
constructor(name: string, config: CT, core: NapCatCore, obContext: NapCatOneBot11Adapter, actions: ActionMap) {
this.name = name;
this.config = structuredClone(config);
this.core = core;
this.obContext = obContext;
this.actions = actions;
this.logger = core.context.logger;
}
abstract onEvent<T extends OB11EmitEventContent>(event: T): void;
abstract open(): void | Promise<void>;
abstract close(): void | Promise<void>;
abstract reload(config: any): OB11NetworkReloadType | Promise<OB11NetworkReloadType>;
}

View File

@@ -1,7 +1,7 @@
import { OneBotEvent } from '@/onebot/event/OneBotEvent'; import { OneBotEvent } from '@/onebot/event/OneBotEvent';
import { OB11Message } from '@/onebot'; import { OB11Message } from '@/onebot';
import { ActionMap } from '@/onebot/action';
import { NetworkConfigAdapter } from '@/onebot/config/config'; import { NetworkConfigAdapter } from '@/onebot/config/config';
import { IOB11NetworkAdapter } from "@/onebot/network/adapter";
export type OB11EmitEventContent = OneBotEvent | OB11Message; export type OB11EmitEventContent = OneBotEvent | OB11Message;
export enum OB11NetworkReloadType { export enum OB11NetworkReloadType {
@@ -11,23 +11,9 @@ export enum OB11NetworkReloadType {
NetWorkClose = 3, NetWorkClose = 3,
NetWorkOpen = 4 NetWorkOpen = 4
} }
export interface IOB11NetworkAdapter {
actions: ActionMap;
name: string;
isEnable: boolean;
config: NetworkConfigAdapter;
onEvent<T extends OB11EmitEventContent>(event: T): void;
open(): void | Promise<void>;
close(): void | Promise<void>;
reload(config: any): OB11NetworkReloadType | Promise<OB11NetworkReloadType>;
}
export class OB11NetworkManager { export class OB11NetworkManager {
adapters: Map<string, IOB11NetworkAdapter> = new Map(); adapters: Map<string, IOB11NetworkAdapter<NetworkConfigAdapter>> = new Map();
async openAllAdapters() { async openAllAdapters() {
return Promise.all(Array.from(this.adapters.values()).map(adapter => adapter.open())); return Promise.all(Array.from(this.adapters.values()).map(adapter => adapter.open()));
@@ -63,22 +49,22 @@ export class OB11NetworkManager {
})); }));
} }
registerAdapter(adapter: IOB11NetworkAdapter) { registerAdapter<CT extends NetworkConfigAdapter>(adapter: IOB11NetworkAdapter<CT>) {
this.adapters.set(adapter.name, adapter); this.adapters.set(adapter.name, adapter);
} }
async registerAdapterAndOpen(adapter: IOB11NetworkAdapter) { async registerAdapterAndOpen<CT extends NetworkConfigAdapter>(adapter: IOB11NetworkAdapter<CT>) {
this.registerAdapter(adapter); this.registerAdapter(adapter);
await adapter.open(); await adapter.open();
} }
async closeSomeAdapters(adaptersToClose: IOB11NetworkAdapter[]) { async closeSomeAdapters<CT extends NetworkConfigAdapter>(adaptersToClose: IOB11NetworkAdapter<CT>[]) {
for (const adapter of adaptersToClose) { for (const adapter of adaptersToClose) {
this.adapters.delete(adapter.name); this.adapters.delete(adapter.name);
await adapter.close(); await adapter.close();
} }
} }
async closeSomeAdaterWhenOpen(adaptersToClose: IOB11NetworkAdapter[]) { async closeSomeAdaterWhenOpen<CT extends NetworkConfigAdapter>(adaptersToClose: IOB11NetworkAdapter<CT>[]) {
for (const adapter of adaptersToClose) { for (const adapter of adaptersToClose) {
this.adapters.delete(adapter.name); this.adapters.delete(adapter.name);
if (adapter.isEnable) { if (adapter.isEnable) {
@@ -91,7 +77,7 @@ export class OB11NetworkManager {
return this.adapters.get(name); return this.adapters.get(name);
} }
async closeAdapterByPredicate(closeFilter: (adapter: IOB11NetworkAdapter) => boolean) { async closeAdapterByPredicate(closeFilter: (adapter: IOB11NetworkAdapter<NetworkConfigAdapter>) => boolean) {
const adaptersToClose = Array.from(this.adapters.values()).filter(closeFilter); const adaptersToClose = Array.from(this.adapters.values()).filter(closeFilter);
await this.closeSomeAdapters(adaptersToClose); await this.closeSomeAdapters(adaptersToClose);
} }
@@ -118,4 +104,4 @@ export class OB11NetworkManager {
export * from './active-http'; export * from './active-http';
export * from './active-websocket'; export * from './active-websocket';
export * from './passive-http'; export * from './passive-http';
export * from './passive-websocket'; export * from './passive-websocket';

View File

@@ -1,4 +1,4 @@
import { IOB11NetworkAdapter, OB11NetworkReloadType } from './index'; import { OB11NetworkReloadType } from './index';
import express, { Express, Request, Response } from 'express'; import express, { Express, Request, Response } from 'express';
import http from 'http'; import http from 'http';
import { NapCatCore } from '@/core'; import { NapCatCore } from '@/core';
@@ -6,20 +6,15 @@ import { OB11Response } from '@/onebot/action/OneBotAction';
import { ActionMap } from '@/onebot/action'; import { ActionMap } from '@/onebot/action';
import cors from 'cors'; import cors from 'cors';
import { HttpServerConfig } from '@/onebot/config/config'; import { HttpServerConfig } from '@/onebot/config/config';
import { NapCatOneBot11Adapter } from "@/onebot";
import { IOB11NetworkAdapter } from "@/onebot/network/adapter";
export class OB11PassiveHttpAdapter implements IOB11NetworkAdapter { export class OB11PassiveHttpAdapter extends IOB11NetworkAdapter<HttpServerConfig> {
private app: Express | undefined; private app: Express | undefined;
private server: http.Server | undefined; private server: http.Server | undefined;
isEnable: boolean = false;
public config: HttpServerConfig;
constructor( constructor(name: string, config: HttpServerConfig, core: NapCatCore, obContext: NapCatOneBot11Adapter, actions: ActionMap) {
public name: string, super(name, config, core, obContext, actions);
config: HttpServerConfig,
public core: NapCatCore,
public actions: ActionMap,
) {
this.config = structuredClone(config);
} }
onEvent() { onEvent() {

View File

@@ -1,36 +1,30 @@
import { IOB11NetworkAdapter, OB11EmitEventContent, OB11NetworkReloadType } from './index'; import { OB11EmitEventContent, OB11NetworkReloadType } from './index';
import urlParse from 'url'; import urlParse from 'url';
import { WebSocket, WebSocketServer } from 'ws'; import { WebSocket, WebSocketServer } from 'ws';
import { Mutex } from 'async-mutex'; import { Mutex } from 'async-mutex';
import { OB11Response } from '@/onebot/action/OneBotAction'; import { OB11Response } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { NapCatCore } from '@/core'; import { NapCatCore } from '@/core';
import { LogWrapper } from '@/common/log';
import { OB11HeartbeatEvent } from '@/onebot/event/meta/OB11HeartbeatEvent'; import { OB11HeartbeatEvent } from '@/onebot/event/meta/OB11HeartbeatEvent';
import { IncomingMessage } from 'http'; import { IncomingMessage } from 'http';
import { ActionMap } from '@/onebot/action'; import { ActionMap } from '@/onebot/action';
import { LifeCycleSubType, OB11LifeCycleEvent } from '@/onebot/event/meta/OB11LifeCycleEvent'; import { LifeCycleSubType, OB11LifeCycleEvent } from '@/onebot/event/meta/OB11LifeCycleEvent';
import { WebsocketServerConfig } from '@/onebot/config/config'; import { WebsocketServerConfig } from '@/onebot/config/config';
import { NapCatOneBot11Adapter } from "@/onebot";
import { IOB11NetworkAdapter } from "@/onebot/network/adapter";
export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter { export class OB11PassiveWebSocketAdapter extends IOB11NetworkAdapter<WebsocketServerConfig> {
wsServer: WebSocketServer; wsServer: WebSocketServer;
wsClients: WebSocket[] = []; wsClients: WebSocket[] = [];
wsClientsMutex = new Mutex(); wsClientsMutex = new Mutex();
isEnable: boolean = false;
heartbeatInterval: number = 0; heartbeatInterval: number = 0;
logger: LogWrapper;
public config: WebsocketServerConfig;
private heartbeatIntervalId: NodeJS.Timeout | null = null; private heartbeatIntervalId: NodeJS.Timeout | null = null;
wsClientWithEvent: WebSocket[] = []; wsClientWithEvent: WebSocket[] = [];
constructor( constructor(
public name: string, name: string, config: WebsocketServerConfig, core: NapCatCore, obContext: NapCatOneBot11Adapter, actions: ActionMap
config: WebsocketServerConfig,
public core: NapCatCore,
public actions: ActionMap,
) { ) {
this.config = structuredClone(config); super(name, config, core, obContext, actions);
this.logger = core.context.logger;
this.wsServer = new WebSocketServer({ this.wsServer = new WebSocketServer({
port: this.config.port, port: this.config.port,
host: this.config.host === '0.0.0.0' ? '' : this.config.host, host: this.config.host === '0.0.0.0' ? '' : this.config.host,

View File

@@ -1,42 +1,37 @@
import { IOB11NetworkAdapter, OB11EmitEventContent, OB11NetworkReloadType } from './index'; import { OB11EmitEventContent, OB11NetworkReloadType } from './index';
import { NapCatOneBot11Adapter, OB11Message } from '@/onebot'; import { NapCatOneBot11Adapter, OB11Message } from '@/onebot';
import { NapCatCore } from '@/core'; import { NapCatCore } from '@/core';
import { AdapterConfig } from '../config/config'; import { PluginConfig } from '../config/config';
import { plugin_onmessage } from '@/plugin'; import { plugin_onmessage } from '@/plugin';
import { ActionMap } from '../action'; import { ActionMap } from '../action';
import { IOB11NetworkAdapter } from "@/onebot/network/adapter";
export class OB11PluginAdapter implements IOB11NetworkAdapter { export class OB11PluginAdapter extends IOB11NetworkAdapter<PluginConfig> {
isEnable: boolean = true;
public config: AdapterConfig;
constructor( constructor(
public name: string, name: string, core: NapCatCore, obContext: NapCatOneBot11Adapter, actions: ActionMap
public core: NapCatCore,
public obCore: NapCatOneBot11Adapter,
public actions: ActionMap,
) { ) {
// 基础配置 const config = {
this.config = {
name: name, name: name,
messagePostFormat: 'array', messagePostFormat: 'array',
reportSelfMessage: false, reportSelfMessage: false,
enable: true, enable: true,
debug: false, debug: false,
} };
super(name, config, core, obContext, actions);
} }
onEvent<T extends OB11EmitEventContent>(event: T) { onEvent<T extends OB11EmitEventContent>(event: T) {
if (event.post_type === 'message') { if (event.post_type === 'message') {
plugin_onmessage(this.config.name, this.core, this.obCore, event as OB11Message,this.actions).then().catch(); plugin_onmessage(this.config.name, this.core, this.obContext, event as OB11Message,this.actions).then().catch();
} }
} }
open() { open() {
this.isEnable = true;
} }
async close() { async close() {
this.isEnable = false;
} }
async reload() { async reload() {

View File

@@ -1,10 +1,10 @@
import { NapCatOneBot11Adapter, OB11Message } from "@/onebot"; import { NapCatOneBot11Adapter, OB11Message } from "@/onebot";
import { NapCatCore } from "../core"; import { NapCatCore } from "@/core";
import { ActionMap } from "@/onebot/action"; import { ActionMap } from "@/onebot/action";
export const plugin_onmessage = async (adapter: string, core: NapCatCore, obCore: NapCatOneBot11Adapter, message: OB11Message, action: ActionMap) => { export const plugin_onmessage = async (adapter: string, core: NapCatCore, obCtx: NapCatOneBot11Adapter, message: OB11Message, action: ActionMap) => {
if (message.raw_message === 'ping') { if (message.raw_message === 'ping') {
const ret = await action.get('send_group_msg')?.handle({ group_id: String(message.group_id), message: 'pong' }, adapter); const ret = await action.get('send_group_msg')?.handle({ group_id: String(message.group_id), message: 'pong' }, adapter);
console.log(ret); console.log(ret);
} }
} };