mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
Merge branch 'main' of https://github.com/NapNeko/NapCatQQ
This commit is contained in:
@@ -33,6 +33,7 @@ import { OB11FriendRequestEvent } from '@/onebot/event/request/OB11FriendRequest
|
|||||||
import { OB11GroupAdminNoticeEvent } from '@/onebot/event/notice/OB11GroupAdminNoticeEvent';
|
import { OB11GroupAdminNoticeEvent } from '@/onebot/event/notice/OB11GroupAdminNoticeEvent';
|
||||||
import { GroupDecreaseSubType, OB11GroupDecreaseEvent } from '@/onebot/event/notice/OB11GroupDecreaseEvent';
|
import { GroupDecreaseSubType, OB11GroupDecreaseEvent } from '@/onebot/event/notice/OB11GroupDecreaseEvent';
|
||||||
import { OB11GroupRequestEvent } from '@/onebot/event/request/OB11GroupRequest';
|
import { OB11GroupRequestEvent } from '@/onebot/event/request/OB11GroupRequest';
|
||||||
|
import { sleep } from '@/common/utils/helper';
|
||||||
|
|
||||||
//OneBot实现类
|
//OneBot实现类
|
||||||
export class NapCatOneBot11Adapter {
|
export class NapCatOneBot11Adapter {
|
||||||
@@ -59,6 +60,15 @@ export class NapCatOneBot11Adapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async InitOneBot() {
|
async InitOneBot() {
|
||||||
|
// 这个延迟对个别 API 的初始化很重要
|
||||||
|
// 例如,如果没有这个延迟,则 getGroupMembers 只能返回空列表
|
||||||
|
// 反向(Active)WebSocket 在初始化后立即连接,如果 QQ 初始化没完成,
|
||||||
|
// 而连接的对方在初始化逻辑中用到这个 getGroupMembers,
|
||||||
|
// 则会导致 getGroupMembers 返回空列表,进而导致初始化失败
|
||||||
|
// 初始化完成的标准尚不明确!
|
||||||
|
// TODO: 弄清楚初始化完成的标志,并试着用监听器回调解决
|
||||||
|
await sleep(2500);
|
||||||
|
|
||||||
const NTQQUserApi = this.core.apis.UserApi;
|
const NTQQUserApi = this.core.apis.UserApi;
|
||||||
const selfInfo = this.core.selfInfo;
|
const selfInfo = this.core.selfInfo;
|
||||||
const ob11Config = this.configLoader.configData;
|
const ob11Config = this.configLoader.configData;
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
import { IOB11NetworkAdapter, OB11EmitEventContent } from '@/onebot/network/index';
|
import { IOB11NetworkAdapter, OB11EmitEventContent } from '@/onebot/network/index';
|
||||||
import { WebSocket } from 'ws';
|
import { WebSocket } from 'ws';
|
||||||
import BaseAction from '@/onebot/action/BaseAction';
|
import BaseAction from '@/onebot/action/BaseAction';
|
||||||
import { sleep } from '@/common/utils/helper';
|
|
||||||
import { OB11HeartbeatEvent } from '../event/meta/OB11HeartbeatEvent';
|
import { OB11HeartbeatEvent } from '../event/meta/OB11HeartbeatEvent';
|
||||||
import { NapCatCore } from '@/core';
|
import { NapCatCore } from '@/core';
|
||||||
import { NapCatOneBot11Adapter } from '../main';
|
import { NapCatOneBot11Adapter } from '../main';
|
||||||
@@ -19,7 +18,7 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
logger: LogWrapper;
|
logger: LogWrapper;
|
||||||
private connection: WebSocket | null = null;
|
private connection: WebSocket | null = null;
|
||||||
private actionMap: Map<string, BaseAction<any, any>> = new Map();
|
private actionMap: Map<string, BaseAction<any, any>> = new Map();
|
||||||
private heartbeatTimer: NodeJS.Timeout | null = null;
|
private heartbeatRef: NodeJS.Timeout | null = null;
|
||||||
private readonly token: string;
|
private readonly token: string;
|
||||||
|
|
||||||
constructor(url: string, reconnectIntervalInMillis: number, heartbeatInterval: number, token:string, coreContext: NapCatCore, onebotContext: NapCatOneBot11Adapter) {
|
constructor(url: string, reconnectIntervalInMillis: number, heartbeatInterval: number, token:string, coreContext: NapCatCore, onebotContext: NapCatOneBot11Adapter) {
|
||||||
@@ -50,6 +49,11 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
if (this.connection) {
|
if (this.connection) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.heartbeatRef = setInterval(() => {
|
||||||
|
if (this.connection && this.connection.readyState === WebSocket.OPEN) {
|
||||||
|
this.connection.send(JSON.stringify(new OB11HeartbeatEvent(this.coreContext, this.heartbeatInterval, this.coreContext.selfInfo.online, true)));
|
||||||
|
}
|
||||||
|
}, this.heartbeatInterval);
|
||||||
await this.tryConnect();
|
await this.tryConnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,19 +68,9 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
this.connection.close();
|
this.connection.close();
|
||||||
this.connection = null;
|
this.connection = null;
|
||||||
}
|
}
|
||||||
if (this.heartbeatTimer) {
|
if (this.heartbeatRef) {
|
||||||
clearInterval(this.heartbeatTimer);
|
clearInterval(this.heartbeatRef);
|
||||||
this.heartbeatTimer = null;
|
this.heartbeatRef = null;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private registerHeartBeat() {
|
|
||||||
if (this.connection) {
|
|
||||||
this.heartbeatTimer = setInterval(() => {
|
|
||||||
if (this.connection && this.connection.readyState === WebSocket.OPEN) {
|
|
||||||
this.connection.send(JSON.stringify(new OB11HeartbeatEvent(this.coreContext, this.heartbeatInterval, this.coreContext.selfInfo.online, true)));
|
|
||||||
}
|
|
||||||
}, this.heartbeatInterval);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,31 +81,40 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async tryConnect() {
|
private async tryConnect() {
|
||||||
while (!this.connection && !this.isClosed) {
|
if (!this.connection && !this.isClosed) {
|
||||||
try {
|
let isClosedByError = false;
|
||||||
this.connection = new WebSocket(this.url, {
|
|
||||||
headers: {
|
this.connection = new WebSocket(this.url, {
|
||||||
'X-Self-ID': this.coreContext.selfInfo.uin,
|
headers: {
|
||||||
'Authorization': `Bearer ${this.token}`,
|
'X-Self-ID': this.coreContext.selfInfo.uin,
|
||||||
'x-client-role': 'Universal', // koishi-adapter-onebot 需要这个字段
|
'Authorization': `Bearer ${this.token}`,
|
||||||
'User-Agent': 'OneBot/11',
|
'x-client-role': 'Universal', // koishi-adapter-onebot 需要这个字段
|
||||||
}
|
'User-Agent': 'OneBot/11',
|
||||||
});
|
},
|
||||||
this.connection.on('message', (data) => {
|
|
||||||
this.handleMessage(data);
|
});
|
||||||
});
|
this.connection.on('message', (data) => {
|
||||||
this.connection.once('close', () => {
|
this.handleMessage(data);
|
||||||
|
});
|
||||||
|
this.connection.once('close', () => {
|
||||||
|
if (!isClosedByError) {
|
||||||
|
this.logger.logError(`反向WebSocket (${this.url}) 连接意外关闭`);
|
||||||
|
this.logger.logError(`在 ${Math.floor(this.reconnectIntervalInMillis / 1000)} 秒后尝试重新连接`);
|
||||||
if (!this.isClosed) {
|
if (!this.isClosed) {
|
||||||
this.connection = null;
|
this.connection = null;
|
||||||
setTimeout(() => this.tryConnect(), this.reconnectIntervalInMillis);
|
setTimeout(() => this.tryConnect(), this.reconnectIntervalInMillis);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
this.registerHeartBeat();
|
});
|
||||||
} catch (e) {
|
this.connection.on('error', (err) => {
|
||||||
this.connection = null;
|
isClosedByError = true;
|
||||||
console.log('Failed to connect to the server, retrying in 5 seconds...');
|
this.logger.logError(`反向WebSocket (${this.url}) 连接错误`, err);
|
||||||
await sleep(5000);
|
this.logger.logError(`在 ${Math.floor(this.reconnectIntervalInMillis / 1000)} 秒后尝试重新连接`);
|
||||||
}
|
if (!this.isClosed) {
|
||||||
|
this.connection = null;
|
||||||
|
setTimeout(() => this.tryConnect(), this.reconnectIntervalInMillis);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user