mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2024-11-21 09:36:35 +00:00
Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
7b1b503703
@ -9,6 +9,8 @@ import { LegacyNTEventWrapper } from '@/common/framework/event-legacy';
|
|||||||
import { NTQQFileApi, NTQQFriendApi, NTQQGroupApi, NTQQMsgApi, NTQQSystemApi, NTQQUserApi, NTQQWebApi } from './apis';
|
import { NTQQFileApi, NTQQFriendApi, NTQQGroupApi, NTQQMsgApi, NTQQSystemApi, NTQQUserApi, NTQQWebApi } from './apis';
|
||||||
import os from 'node:os';
|
import os from 'node:os';
|
||||||
import { NTQQCollectionApi } from './apis/collection';
|
import { NTQQCollectionApi } from './apis/collection';
|
||||||
|
import { OB11Config } from '@/onebot/helper/config';
|
||||||
|
import { NapCatConfig } from './helper/config';
|
||||||
|
|
||||||
export enum NapCatCoreWorkingEnv {
|
export enum NapCatCoreWorkingEnv {
|
||||||
Unknown = 0,
|
Unknown = 0,
|
||||||
@ -36,6 +38,7 @@ export class NapCatCore {
|
|||||||
// runtime info, not readonly
|
// runtime info, not readonly
|
||||||
selfInfo: SelfInfo;
|
selfInfo: SelfInfo;
|
||||||
util: NodeQQNTWrapperUtil;
|
util: NodeQQNTWrapperUtil;
|
||||||
|
config: any;
|
||||||
|
|
||||||
// 通过构造器递过去的 runtime info 应该尽量少
|
// 通过构造器递过去的 runtime info 应该尽量少
|
||||||
constructor(context: InstanceContext, selfInfo: SelfInfo) {
|
constructor(context: InstanceContext, selfInfo: SelfInfo) {
|
||||||
@ -53,6 +56,7 @@ export class NapCatCore {
|
|||||||
UserApi: new NTQQUserApi(this.context, this),
|
UserApi: new NTQQUserApi(this.context, this),
|
||||||
GroupApi: new NTQQGroupApi(this.context, this),
|
GroupApi: new NTQQGroupApi(this.context, this),
|
||||||
};
|
};
|
||||||
|
this.config = new NapCatConfig(this,this.context.pathWrapper.cachePath);
|
||||||
this.NapCatDataPath = path.join(this.dataPath, 'NapCat');
|
this.NapCatDataPath = path.join(this.dataPath, 'NapCat');
|
||||||
fs.mkdirSync(this.NapCatDataPath, { recursive: true });
|
fs.mkdirSync(this.NapCatDataPath, { recursive: true });
|
||||||
this.NapCatTempPath = path.join(this.NapCatDataPath, 'temp');
|
this.NapCatTempPath = path.join(this.NapCatDataPath, 'temp');
|
||||||
|
16
src/core/helper/config.ts
Normal file
16
src/core/helper/config.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { ConfigBase } from "@/common/utils/ConfigBase";
|
||||||
|
import { LogLevel } from "@/common/utils/log";
|
||||||
|
|
||||||
|
export interface NapCatConfig {
|
||||||
|
fileLog: boolean,
|
||||||
|
consoleLog: boolean,
|
||||||
|
fileLogLevel: LogLevel,
|
||||||
|
consoleLogLevel: LogLevel,
|
||||||
|
}
|
||||||
|
|
||||||
|
export class NapCatConfig extends ConfigBase<NapCatConfig> {
|
||||||
|
getConfigName() {
|
||||||
|
return 'onebot11';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -55,7 +55,9 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
|
|
||||||
close() {
|
close() {
|
||||||
if (this.isClosed) {
|
if (this.isClosed) {
|
||||||
throw new Error('Cannot close a closed WebSocket connection');
|
this.logger.logDebug('Cannot close a closed WebSocket connection');
|
||||||
|
return;
|
||||||
|
//throw new Error('Cannot close a closed WebSocket connection');
|
||||||
}
|
}
|
||||||
this.isClosed = true;
|
this.isClosed = true;
|
||||||
if (this.connection) {
|
if (this.connection) {
|
||||||
|
@ -4,6 +4,7 @@ import express, { Express, Request, Response } from 'express';
|
|||||||
import http from 'http';
|
import http from 'http';
|
||||||
import { NapCatCore } from '@/core';
|
import { NapCatCore } from '@/core';
|
||||||
import { NapCatOneBot11Adapter } from '../main';
|
import { NapCatOneBot11Adapter } from '../main';
|
||||||
|
import { OB11Response } from '../action/OB11Response';
|
||||||
|
|
||||||
export class OB11PassiveHttpAdapter implements IOB11NetworkAdapter {
|
export class OB11PassiveHttpAdapter implements IOB11NetworkAdapter {
|
||||||
token: string;
|
token: string;
|
||||||
@ -12,7 +13,6 @@ export class OB11PassiveHttpAdapter implements IOB11NetworkAdapter {
|
|||||||
private app: Express | undefined;
|
private app: Express | undefined;
|
||||||
private server: http.Server | undefined;
|
private server: http.Server | undefined;
|
||||||
private isOpen: boolean = false;
|
private isOpen: boolean = false;
|
||||||
private hasBeenClosed: boolean = false;
|
|
||||||
private actionMap: Map<string, BaseAction<any, any>> = new Map();
|
private actionMap: Map<string, BaseAction<any, any>> = new Map();
|
||||||
private port: number;
|
private port: number;
|
||||||
|
|
||||||
@ -36,18 +36,23 @@ export class OB11PassiveHttpAdapter implements IOB11NetworkAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
open() {
|
open() {
|
||||||
if (this.hasBeenClosed) {
|
try {
|
||||||
this.coreContext.context.logger.logError('Cannot open a closed HTTP server');
|
if (this.isOpen) {
|
||||||
}
|
this.coreContext.context.logger.logError('Cannot open a closed HTTP server');
|
||||||
if (!this.isOpen) {
|
return;
|
||||||
this.initializeServer();
|
}
|
||||||
this.isOpen = true;
|
if (!this.isOpen) {
|
||||||
|
this.initializeServer();
|
||||||
|
this.isOpen = true;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
this.coreContext.context.logger.logError(`[OneBot] [HTTP Server Adapter] Boot Error: ${e}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async close() {
|
async close() {
|
||||||
this.isOpen = false;
|
this.isOpen = false;
|
||||||
this.hasBeenClosed = true;
|
|
||||||
this.server?.close();
|
this.server?.close();
|
||||||
this.app = undefined;
|
this.app = undefined;
|
||||||
}
|
}
|
||||||
@ -58,30 +63,51 @@ export class OB11PassiveHttpAdapter implements IOB11NetworkAdapter {
|
|||||||
|
|
||||||
this.app.use(express.json());
|
this.app.use(express.json());
|
||||||
this.app.use(express.urlencoded({ extended: false }));
|
this.app.use(express.urlencoded({ extended: false }));
|
||||||
|
this.app.use((req, res, next) => this.authorize(this.token, req, res, next));
|
||||||
this.app.use('/', (req, res) => this.handleRequest(req, res));
|
this.app.use('/', (req, res) => this.handleRequest(req, res));
|
||||||
|
|
||||||
this.server.listen(this.port, () => {
|
this.server.listen(this.port, () => {
|
||||||
this.coreContext.context.logger.log(`HTTP server listening on port ${this.port}`);
|
this.coreContext.context.logger.log(`[OneBot] [HTTP Server Adapter] Start On Port ${this.port}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private authorize(token: string | undefined, req: Request, res: Response, next: any) {
|
||||||
|
if (!token || token.length == 0) return;//客户端未设置密钥
|
||||||
|
const HeaderClientToken = req.headers.authorization?.split('Bearer ').pop() || '';
|
||||||
|
const QueryClientToken = req.query.access_token;
|
||||||
|
const ClientToken = typeof (QueryClientToken) === 'string' && QueryClientToken !== '' ? QueryClientToken : HeaderClientToken;
|
||||||
|
if (ClientToken === token) {
|
||||||
|
next();
|
||||||
|
} else {
|
||||||
|
res.status(403).send(JSON.stringify({ message: 'token verify failed!' }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async handleRequest(req: Request, res: Response) {
|
private async handleRequest(req: Request, res: Response) {
|
||||||
if (!this.isOpen) {
|
if (!this.isOpen) {
|
||||||
res.status(503).send('Server is closed');
|
this.coreContext.context.logger.log(`[OneBot] [HTTP Server Adapter] Server is closed`);
|
||||||
|
res.json(OB11Response.error('Server is closed', 200));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let payload = req.body;
|
||||||
|
if (req.method == 'get') {
|
||||||
|
payload = req.query;
|
||||||
|
} else if (req.query) {
|
||||||
|
payload = { ...req.query, ...req.body };
|
||||||
|
}
|
||||||
|
|
||||||
const actionName = req.path.split('/')[1];
|
const actionName = req.path.split('/')[1];
|
||||||
const action = this.actionMap.get(actionName);
|
const action = this.actionMap.get(actionName);
|
||||||
if (action) {
|
if (action) {
|
||||||
try {
|
try {
|
||||||
const result = await action.handle(req.body);
|
const result = await action.handle(payload);
|
||||||
res.json(result);
|
res.json(result);
|
||||||
} catch (error) {
|
} catch (error: any) {
|
||||||
res.status(500).send('Internal Server Error');
|
res.json(OB11Response.error(error?.stack?.toString() || error?.message || 'Error Handle', 200));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
res.status(404).send('Action not found');
|
res.json(OB11Response.error('不支持的api ' + actionName, 200));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,8 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
//鉴权
|
//鉴权
|
||||||
this.authorize(token, wsClient, wsReq);
|
this.authorize(token, wsClient, wsReq);
|
||||||
|
|
||||||
|
wsClient.on('error', (err) => this.logger.log('[OneBot] [WebSocket Server] Client Error:', err.message));
|
||||||
|
|
||||||
wsClient.on('message', (message) => {
|
wsClient.on('message', (message) => {
|
||||||
this.handleMessage(wsClient, message).then().catch(this.logger.logError);
|
this.handleMessage(wsClient, message).then().catch(this.logger.logError);
|
||||||
});
|
});
|
||||||
@ -53,7 +55,7 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
await this.wsClientsMutex.runExclusive(async () => {
|
await this.wsClientsMutex.runExclusive(async () => {
|
||||||
this.wsClients.push(wsClient);
|
this.wsClients.push(wsClient);
|
||||||
});
|
});
|
||||||
});
|
}).on('error', (err) => this.logger.log('[OneBot] [WebSocket Server] Server Error:', err.message));
|
||||||
}
|
}
|
||||||
|
|
||||||
registerActionMap(actionMap: Map<string, BaseAction<any, any>>) {
|
registerActionMap(actionMap: Map<string, BaseAction<any, any>>) {
|
||||||
@ -67,25 +69,25 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
onEvent<T extends OB11EmitEventContent>(event: T) {
|
onEvent<T extends OB11EmitEventContent>(event: T) {
|
||||||
this.wsClientsMutex.runExclusive(async () => {
|
this.wsClientsMutex.runExclusive(async () => {
|
||||||
this.wsClients.forEach((wsClient) => {
|
this.wsClients.forEach((wsClient) => {
|
||||||
const wrappedEvent = this.wrapEvent(event);
|
wsClient.send(JSON.stringify(event));
|
||||||
wsClient.send(JSON.stringify(wrappedEvent));
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
open() {
|
open() {
|
||||||
if (this.hasBeenClosed) {
|
if (this.isOpen) {
|
||||||
this.logger.logError('Cannot open a closed WebSocket server');
|
this.logger.logError('[OneBot] [WebSocket Server] Cannot open a opened WebSocket server');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.logger.log('WebSocket server started', this.wsServer.address());
|
let addressInfo = this.wsServer.address();
|
||||||
|
this.logger.log('[OneBot] [WebSocket Server] Server Started', typeof (addressInfo) === 'string' ? addressInfo : addressInfo?.address + ':' + addressInfo?.port);
|
||||||
|
|
||||||
this.isOpen = true;
|
this.isOpen = true;
|
||||||
this.registerHeartBeat();
|
this.registerHeartBeat();
|
||||||
}
|
}
|
||||||
|
|
||||||
async close() {
|
async close() {
|
||||||
this.isOpen = false;
|
this.isOpen = false;
|
||||||
this.hasBeenClosed = true;
|
|
||||||
this.wsServer.close();
|
this.wsServer.close();
|
||||||
if (this.heartbeatIntervalId) {
|
if (this.heartbeatIntervalId) {
|
||||||
clearInterval(this.heartbeatIntervalId);
|
clearInterval(this.heartbeatIntervalId);
|
||||||
@ -117,14 +119,6 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
wsClient.close();
|
wsClient.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async checkStateAndAnnounce<T>(data: T) {
|
|
||||||
await this.wsClientsMutex.runExclusive(async () => {
|
|
||||||
this.wsClients.forEach((wsClient) => {
|
|
||||||
this.checkStateAndReply(data, wsClient);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private checkStateAndReply<T>(data: T, wsClient: WebSocket) {
|
private checkStateAndReply<T>(data: T, wsClient: WebSocket) {
|
||||||
if (wsClient.readyState === WebSocket.OPEN) {
|
if (wsClient.readyState === WebSocket.OPEN) {
|
||||||
wsClient.send(JSON.stringify(data));
|
wsClient.send(JSON.stringify(data));
|
||||||
@ -138,7 +132,7 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
try {
|
try {
|
||||||
receiveData = JSON.parse(message.toString());
|
receiveData = JSON.parse(message.toString());
|
||||||
echo = receiveData.echo;
|
echo = receiveData.echo;
|
||||||
this.logger.logDebug('收到正向Websocket消息', receiveData);
|
//this.logger.logDebug('收到正向Websocket消息', receiveData);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.checkStateAndReply<any>(OB11Response.error('json解析失败,请检查数据格式', 1400, echo), wsClient);
|
this.checkStateAndReply<any>(OB11Response.error('json解析失败,请检查数据格式', 1400, echo), wsClient);
|
||||||
}
|
}
|
||||||
@ -151,11 +145,5 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private wrapEvent<T extends OB11EmitEventContent>(event: T) {
|
|
||||||
return {
|
|
||||||
type: 'event',
|
|
||||||
data: event,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user