From 88fd1f9eb1aefd374a4a8e391ee27cb7f63c6377 Mon Sep 17 00:00:00 2001 From: stapxs <1007028430.stapx@gmail.com> Date: Thu, 9 Jan 2025 13:22:46 +0800 Subject: [PATCH 1/2] =?UTF-8?q?http=20sse=20=E6=B6=88=E6=81=AF=E4=B8=8A?= =?UTF-8?q?=E6=8A=A5=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/onebot/config/config.ts | 9 ++++ src/onebot/index.ts | 13 +++++- src/onebot/network/active-http-sse.ts | 60 +++++++++++++++++++++++++++ src/onebot/network/passive-http.ts | 6 +-- 4 files changed, 84 insertions(+), 4 deletions(-) create mode 100644 src/onebot/network/active-http-sse.ts diff --git a/src/onebot/config/config.ts b/src/onebot/config/config.ts index d4032e268..66c56d344 100644 --- a/src/onebot/config/config.ts +++ b/src/onebot/config/config.ts @@ -59,6 +59,13 @@ export const httpServerDefaultConfigs = createDefaultAdapterConfig({ }); export type HttpServerConfig = typeof httpServerDefaultConfigs; +export const httpSseServerDefaultConfigs = createDefaultAdapterConfig({ + ...httpServerDefaultConfigs, + name: 'http-sse-server', + reportSelfMessage: false, +}); +export type HttpSseServerConfig = typeof httpSseServerDefaultConfigs; + export const httpClientDefaultConfigs = createDefaultAdapterConfig({ name: 'http-client', enable: false as boolean, @@ -99,6 +106,7 @@ export type WebsocketClientConfig = typeof websocketClientDefaultConfigs; export interface NetworkConfig { httpServers: Array; + httpSseServers: Array; httpClients: Array; websocketServers: Array; websocketClients: Array; @@ -120,6 +128,7 @@ const createDefaultConfig = (config: T): T => config; export const defaultOneBotConfigs = createDefaultConfig({ network: { httpServers: [], + httpSseServers: [], httpClients: [], websocketServers: [], websocketClients: [], diff --git a/src/onebot/index.ts b/src/onebot/index.ts index 0c6515911..0eaa74eae 100644 --- a/src/onebot/index.ts +++ b/src/onebot/index.ts @@ -53,6 +53,7 @@ import { import { OB11Message } from './types'; import { OB11PluginAdapter } from './network/plugin'; import { IOB11NetworkAdapter } from "@/onebot/network/adapter"; +import { OB11ActiveHttpSSEAdapter } from './network/active-http-sse'; //OneBot实现类 export class NapCatOneBot11Adapter { @@ -87,6 +88,9 @@ export class NapCatOneBot11Adapter { for (const key of ob11Config.network.httpServers) { log += `HTTP服务: ${key.host}:${key.port}, : ${key.enable ? '已启动' : '未启动'}\n`; } + for (const key of ob11Config.network.httpSseServers) { + log += `HTTP-SSE服务: ${key.host}:${key.port}, : ${key.enable ? '已启动' : '未启动'}\n`; + } for (const key of ob11Config.network.httpClients) { log += `HTTP上报服务: ${key.url}, : ${key.enable ? '已启动' : '未启动'}\n`; } @@ -125,6 +129,13 @@ export class NapCatOneBot11Adapter { ); } } + for(const key of ob11Config.network.httpSseServers){ + if(key.enable) { + this.networkManager.registerAdapter( + new OB11ActiveHttpSSEAdapter(key.name, key, this.core, this, this.actions) + ); + } + } for (const key of ob11Config.network.httpClients) { if (key.enable) { this.networkManager.registerAdapter( @@ -389,7 +400,7 @@ export class NapCatOneBot11Adapter { ) { this.context.logger.logDebug('有加群请求'); try { - let requestUin = await this.core.apis.UserApi.getUinByUidV2(notify.user1.uid); + const requestUin = await this.core.apis.UserApi.getUinByUidV2(notify.user1.uid); const groupRequestEvent = new OB11GroupRequestEvent( this.core, parseInt(notify.group.groupCode), diff --git a/src/onebot/network/active-http-sse.ts b/src/onebot/network/active-http-sse.ts new file mode 100644 index 000000000..c52ce7dea --- /dev/null +++ b/src/onebot/network/active-http-sse.ts @@ -0,0 +1,60 @@ +import { OB11EmitEventContent } from './index'; +import { Request, Response } from 'express'; +import { OB11Response } from '@/onebot/action/OneBotAction'; +import { OB11PassiveHttpAdapter } from './passive-http'; + +export class OB11ActiveHttpSSEAdapter extends OB11PassiveHttpAdapter { + private sseClients: Response[] = []; + + async handleRequest(req: Request, res: Response): Promise { + if (!this.isEnable) { + this.core.context.logger.log(`[OneBot] [HTTP Server Adapter] Server is closed`); + return res.json(OB11Response.error('Server is closed', 200)); + } + + let payload = req.body; + if (req.method == 'get') { + payload = req.query; + } else if (req.query) { + payload = { ...req.query, ...req.body }; + } + if (req.path === '' || req.path === '/') { + const hello = OB11Response.ok({}); + hello.message = 'NapCat4 Ss Running'; + return res.json(hello); + } + if (req.path === '/_events') { + return this.createSseSupport(req, res); + } + const actionName = req.path.split('/')[1]; + const action = this.actions.get(actionName as any); + if (action) { + try { + const result = await action.handle(payload, this.name); + return res.json(result); + } catch (error: any) { + return res.json(OB11Response.error(error?.stack?.toString() || error?.message || 'Error Handle', 200)); + } + } else { + return res.json(OB11Response.error('不支持的Api ' + actionName, 200)); + } + } + + private async createSseSupport(req: Request, res: Response) { + res.setHeader('Content-Type', 'text/event-stream'); + res.setHeader('Cache-Control', 'no-cache'); + res.setHeader('Connection', 'keep-alive'); + res.flushHeaders(); + + this.sseClients.push(res); + req.on('close', () => { + this.sseClients = this.sseClients.filter((client) => client !== res); + }); + } + + onEvent(event: T) { + this.sseClients.forEach((res) => { + res.write(`data: ${JSON.stringify(event)}\n\n`); + }); + } +} diff --git a/src/onebot/network/passive-http.ts b/src/onebot/network/passive-http.ts index e05aaa32d..03bd53e6f 100644 --- a/src/onebot/network/passive-http.ts +++ b/src/onebot/network/passive-http.ts @@ -1,4 +1,4 @@ -import { OB11NetworkReloadType } from './index'; +import { OB11EmitEventContent, OB11NetworkReloadType } from './index'; import express, { Express, Request, Response } from 'express'; import http from 'http'; import { NapCatCore } from '@/core'; @@ -17,7 +17,7 @@ export class OB11PassiveHttpAdapter extends IOB11NetworkAdapter(event: T) { // http server is passive, no need to emit event } @@ -82,7 +82,7 @@ export class OB11PassiveHttpAdapter extends IOB11NetworkAdapter Date: Thu, 9 Jan 2025 13:42:55 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E8=B4=A8=E9=87=8F=E4=BF=9D=E9=9A=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/onebot/network/active-http-sse.ts | 28 +-------------------------- src/onebot/network/passive-http.ts | 16 +++++++++------ 2 files changed, 11 insertions(+), 33 deletions(-) diff --git a/src/onebot/network/active-http-sse.ts b/src/onebot/network/active-http-sse.ts index c52ce7dea..dbe4eaf44 100644 --- a/src/onebot/network/active-http-sse.ts +++ b/src/onebot/network/active-http-sse.ts @@ -7,36 +7,10 @@ export class OB11ActiveHttpSSEAdapter extends OB11PassiveHttpAdapter { private sseClients: Response[] = []; async handleRequest(req: Request, res: Response): Promise { - if (!this.isEnable) { - this.core.context.logger.log(`[OneBot] [HTTP Server Adapter] Server is closed`); - return res.json(OB11Response.error('Server is closed', 200)); - } - - let payload = req.body; - if (req.method == 'get') { - payload = req.query; - } else if (req.query) { - payload = { ...req.query, ...req.body }; - } - if (req.path === '' || req.path === '/') { - const hello = OB11Response.ok({}); - hello.message = 'NapCat4 Ss Running'; - return res.json(hello); - } if (req.path === '/_events') { return this.createSseSupport(req, res); - } - const actionName = req.path.split('/')[1]; - const action = this.actions.get(actionName as any); - if (action) { - try { - const result = await action.handle(payload, this.name); - return res.json(result); - } catch (error: any) { - return res.json(OB11Response.error(error?.stack?.toString() || error?.message || 'Error Handle', 200)); - } } else { - return res.json(OB11Response.error('不支持的Api ' + actionName, 200)); + super.httpApiRequest(req, res); } } diff --git a/src/onebot/network/passive-http.ts b/src/onebot/network/passive-http.ts index 03bd53e6f..7ed48481e 100644 --- a/src/onebot/network/passive-http.ts +++ b/src/onebot/network/passive-http.ts @@ -82,12 +82,7 @@ export class OB11PassiveHttpAdapter extends IOB11NetworkAdapter