mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2024-11-21 09:36:35 +00:00
refactor: move Ob11Adapter to index.ts
This commit is contained in:
parent
234046ce10
commit
6b9307de2a
@ -8,8 +8,8 @@ import { SelfInfo } from '@/core/entities';
|
||||
import { LoginListener } from '@/core/listeners';
|
||||
import { NodeIKernelLoginService } from '@/core/services';
|
||||
import { NodeIQQNTWrapperSession, WrapperNodeApi } from '@/core/wrapper/wrapper';
|
||||
import { NapCatOneBot11Adapter } from '@/onebot/main';
|
||||
import { InitWebUi } from '@/webui';
|
||||
import { NapCatOneBot11Adapter } from '@/onebot';
|
||||
|
||||
//Framework ES入口文件
|
||||
export async function NCoreInitFramework(
|
||||
|
@ -3,7 +3,8 @@ import { OB11Response } from './OB11Response';
|
||||
import { OB11Return } from '@/onebot/types';
|
||||
import Ajv, { ErrorObject, ValidateFunction } from 'ajv';
|
||||
import { NapCatCore } from '@/core';
|
||||
import { NapCatOneBot11Adapter } from '../main';
|
||||
|
||||
import { NapCatOneBot11Adapter } from '@/onebot';
|
||||
|
||||
abstract class BaseAction<PayloadType, ReturnDataType> {
|
||||
actionName: ActionName = ActionName.Unknown;
|
||||
|
@ -74,7 +74,8 @@ import { FetchCustomFace } from './extends/FetchCustomFace';
|
||||
import GoCQHTTPUploadPrivateFile from './go-cqhttp/UploadPrivareFile';
|
||||
import { FetchEmojiLike } from './extends/FetchEmojiLike';
|
||||
import { NapCatCore } from '@/core';
|
||||
import { NapCatOneBot11Adapter } from '../main';
|
||||
|
||||
import { NapCatOneBot11Adapter } from '@/onebot';
|
||||
|
||||
export function createActionMap(onebotContext: NapCatOneBot11Adapter, coreContext: NapCatCore) {
|
||||
const actionHandlers = [
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { NapCatCore } from '@/core';
|
||||
import { NapCatOneBot11Adapter } from '../main';
|
||||
|
||||
import { NapCatOneBot11Adapter } from '@/onebot';
|
||||
|
||||
export class OneBotFriendApi {
|
||||
obContext: NapCatOneBot11Adapter;
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { NapCatCore } from '@/core';
|
||||
import { NapCatOneBot11Adapter } from '../main';
|
||||
|
||||
import { NapCatOneBot11Adapter } from '@/onebot';
|
||||
|
||||
export class OneBotGroupApi {
|
||||
obContext: NapCatOneBot11Adapter;
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { NapCatCore } from '@/core';
|
||||
import { NapCatOneBot11Adapter } from '../main';
|
||||
|
||||
import { NapCatOneBot11Adapter } from '@/onebot';
|
||||
|
||||
export class OneBotUserApi {
|
||||
obContext: NapCatOneBot11Adapter;
|
||||
|
@ -1,2 +1,406 @@
|
||||
export * from './main';
|
||||
export * from './types';
|
||||
import {
|
||||
BuddyListener,
|
||||
BuddyReqType,
|
||||
ChatType,
|
||||
GroupListener,
|
||||
GroupNotifyTypes,
|
||||
InstanceContext,
|
||||
MsgListener,
|
||||
NapCatCore,
|
||||
RawMessage,
|
||||
} from '@/core';
|
||||
import { OB11Config, OB11ConfigLoader } from '@/onebot/helper/config';
|
||||
import { OneBotApiContextType } from '@/onebot/types';
|
||||
import {
|
||||
OB11ActiveHttpAdapter,
|
||||
OB11ActiveWebSocketAdapter,
|
||||
OB11NetworkManager,
|
||||
OB11PassiveHttpAdapter,
|
||||
OB11PassiveWebSocketAdapter,
|
||||
} from '@/onebot/network';
|
||||
import { NapCatPathWrapper } from '@/common/framework/napcat';
|
||||
import { OneBotFriendApi, OneBotGroupApi, OneBotUserApi } from '@/onebot/api';
|
||||
import { createActionMap } from '@/onebot/action';
|
||||
import { WebUiDataRuntime } from '@/webui/src/helper/Data';
|
||||
import { OB11InputStatusEvent } from '@/onebot/event/notice/OB11InputStatusEvent';
|
||||
import { MessageUnique } from '@/common/utils/MessageUnique';
|
||||
import { OB11Constructor } from '@/onebot/helper/data';
|
||||
import { logOB11Message } from '@/onebot/helper/log';
|
||||
import { proxiedListenerOf } from '@/common/utils/proxy-handler';
|
||||
import { OB11FriendRequestEvent } from '@/onebot/event/request/OB11FriendRequest';
|
||||
import { OB11GroupAdminNoticeEvent } from '@/onebot/event/notice/OB11GroupAdminNoticeEvent';
|
||||
import { GroupDecreaseSubType, OB11GroupDecreaseEvent } from '@/onebot/event/notice/OB11GroupDecreaseEvent';
|
||||
import { OB11GroupRequestEvent } from '@/onebot/event/request/OB11GroupRequest';
|
||||
import { OB11FriendRecallNoticeEvent } from '@/onebot/event/notice/OB11FriendRecallNoticeEvent';
|
||||
import { OB11GroupRecallNoticeEvent } from '@/onebot/event/notice/OB11GroupRecallNoticeEvent';
|
||||
|
||||
//OneBot实现类
|
||||
export class NapCatOneBot11Adapter {
|
||||
readonly core: NapCatCore;
|
||||
readonly context: InstanceContext;
|
||||
|
||||
configLoader: OB11ConfigLoader;
|
||||
apiContext: OneBotApiContextType;
|
||||
networkManager: OB11NetworkManager;
|
||||
|
||||
private bootTime = Date.now() / 1000;
|
||||
|
||||
constructor(core: NapCatCore, context: InstanceContext, pathWrapper: NapCatPathWrapper) {
|
||||
this.core = core;
|
||||
this.context = context;
|
||||
this.configLoader = new OB11ConfigLoader(core, pathWrapper.configPath);
|
||||
this.apiContext = {
|
||||
GroupApi: new OneBotGroupApi(this, core),
|
||||
UserApi: new OneBotUserApi(this, core),
|
||||
FriendApi: new OneBotFriendApi(this, core),
|
||||
};
|
||||
this.networkManager = new OB11NetworkManager();
|
||||
this.InitOneBot().then().catch(e => this.context.logger.logError('初始化OneBot失败', e));
|
||||
}
|
||||
|
||||
async InitOneBot() {
|
||||
const NTQQUserApi = this.core.apis.UserApi;
|
||||
const selfInfo = this.core.selfInfo;
|
||||
const ob11Config = this.configLoader.configData;
|
||||
|
||||
const serviceInfo = `
|
||||
HTTP服务 ${ob11Config.http.enable ? '已启动' : '未启动'}, ${ob11Config.http.host}:${ob11Config.http.port}
|
||||
HTTP上报服务 ${ob11Config.http.enablePost ? '已启动' : '未启动'}, 上报地址: ${ob11Config.http.postUrls}
|
||||
WebSocket服务 ${ob11Config.ws.enable ? '已启动' : '未启动'}, ${ob11Config.ws.host}:${ob11Config.ws.port}
|
||||
WebSocket反向服务 ${ob11Config.reverseWs.enable ? '已启动' : '未启动'}, 反向地址: ${ob11Config.reverseWs.urls}`;
|
||||
|
||||
NTQQUserApi.getUserDetailInfo(selfInfo.uid).then(user => {
|
||||
selfInfo.nick = user.nick;
|
||||
this.context.logger.setLogSelfInfo(selfInfo);
|
||||
}).catch(this.context.logger.logError);
|
||||
this.context.logger.log(`[Notice] [OneBot11] ${serviceInfo}`);
|
||||
|
||||
//创建NetWork服务
|
||||
const actions = createActionMap(this, this.core);
|
||||
if (ob11Config.http.enable) {
|
||||
await this.networkManager.registerAdapter(new OB11PassiveHttpAdapter(
|
||||
ob11Config.http.port, ob11Config.token, this.core, this,
|
||||
));
|
||||
}
|
||||
if (ob11Config.http.enablePost) {
|
||||
ob11Config.http.postUrls.forEach(url => {
|
||||
this.networkManager.registerAdapter(new OB11ActiveHttpAdapter(
|
||||
url, ob11Config.heartInterval, ob11Config.token, this.core, this,
|
||||
));
|
||||
});
|
||||
}
|
||||
if (ob11Config.ws.enable) {
|
||||
const OBPassiveWebSocketAdapter = new OB11PassiveWebSocketAdapter(
|
||||
ob11Config.ws.host, ob11Config.ws.port, ob11Config.heartInterval, ob11Config.token, this.core, this,
|
||||
);
|
||||
await this.networkManager.registerAdapter(OBPassiveWebSocketAdapter);
|
||||
}
|
||||
if (ob11Config.reverseWs.enable) {
|
||||
ob11Config.reverseWs.urls.forEach(url => {
|
||||
this.networkManager.registerAdapter(new OB11ActiveWebSocketAdapter(
|
||||
url, 5000, ob11Config.heartInterval, ob11Config.token, this.core, this,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
await this.networkManager.registerAllActions(actions);
|
||||
await this.networkManager.openAllAdapters();
|
||||
|
||||
this.initMsgListener();
|
||||
this.initBuddyListener();
|
||||
this.initGroupListener();
|
||||
|
||||
await WebUiDataRuntime.setQQLoginUin(selfInfo.uin.toString());
|
||||
await WebUiDataRuntime.setQQLoginStatus(true);
|
||||
await WebUiDataRuntime.setOB11ConfigCall(async (ob11: OB11Config) => {
|
||||
this.configLoader.save(ob11);
|
||||
});
|
||||
}
|
||||
|
||||
private initMsgListener() {
|
||||
const msgListener = new MsgListener();
|
||||
|
||||
msgListener.onInputStatusPush = async data => {
|
||||
const uin = await this.core.apis.UserApi.getUinByUidV2(data.fromUin);
|
||||
this.context.logger.log(`[Notice] [输入状态] ${uin} ${data.statusText}`);
|
||||
await this.networkManager.emitEvent(new OB11InputStatusEvent(
|
||||
this.core,
|
||||
parseInt(uin),
|
||||
data.eventType,
|
||||
data.statusText,
|
||||
));
|
||||
};
|
||||
|
||||
msgListener.onRecvMsg = async msg => {
|
||||
for (const m of msg) {
|
||||
if (this.bootTime > parseInt(m.msgTime)) {
|
||||
this.context.logger.logDebug(`消息时间${m.msgTime}早于启动时间${this.bootTime},忽略上报`);
|
||||
continue;
|
||||
}
|
||||
m.id = MessageUnique.createMsg(
|
||||
{
|
||||
chatType: m.chatType,
|
||||
peerUid: m.peerUid,
|
||||
guildId: '',
|
||||
},
|
||||
m.msgId,
|
||||
);
|
||||
await this.emitMsg(m)
|
||||
.catch(e => this.context.logger.logError('处理消息失败', e));
|
||||
}
|
||||
};
|
||||
|
||||
msgListener.onMsgInfoListUpdate = async msgList => {
|
||||
this.emitRecallMsg(msgList)
|
||||
.catch(e => this.context.logger.logError('处理消息失败', e));
|
||||
for (const msg of msgList.filter(e => e.senderUin == this.core.selfInfo.uin)) {
|
||||
// console.log(msg);
|
||||
if (msg.sendStatus == 2) {
|
||||
// 完成后再post
|
||||
OB11Constructor.message(this.core, msg, this.configLoader.configData.messagePostFormat)
|
||||
.then((ob11Msg) => {
|
||||
ob11Msg.target_id = parseInt(msg.peerUin);
|
||||
if (this.configLoader.configData.reportSelfMessage) {
|
||||
msg.id = MessageUnique.createMsg({
|
||||
chatType: msg.chatType,
|
||||
peerUid: msg.peerUid,
|
||||
guildId: '',
|
||||
}, msg.msgId);
|
||||
this.emitMsg(msg);
|
||||
} else {
|
||||
logOB11Message(this.core, ob11Msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.context.session.getMsgService().addKernelMsgListener(
|
||||
new this.context.wrapper.NodeIKernelMsgListener(proxiedListenerOf(msgListener, this.context.logger)),
|
||||
);
|
||||
}
|
||||
|
||||
private initBuddyListener() {
|
||||
const buddyListener = new BuddyListener();
|
||||
|
||||
buddyListener.onBuddyReqChange = reqs => {
|
||||
reqs.buddyReqs.forEach(async req => {
|
||||
if (!!req.isInitiator || (req.isDecide && req.reqType !== BuddyReqType.KMEINITIATORWAITPEERCONFIRM)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const requesterUin = await this.core.apis.UserApi.getUinByUidV2(req.friendUid);
|
||||
await this.networkManager.emitEvent(new OB11FriendRequestEvent(
|
||||
this.core,
|
||||
parseInt(requesterUin!),
|
||||
req.friendUid + '|' + req.reqTime,
|
||||
req.extWords,
|
||||
));
|
||||
} catch (e) {
|
||||
this.context.logger.logDebug('获取加好友者QQ号失败', e);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
this.context.session.getBuddyService().addKernelBuddyListener(
|
||||
new this.context.wrapper.NodeIKernelBuddyListener(proxiedListenerOf(buddyListener, this.context.logger)),
|
||||
);
|
||||
}
|
||||
|
||||
private initGroupListener() {
|
||||
const groupListener = new GroupListener();
|
||||
|
||||
groupListener.onGroupNotifiesUpdated = async (_, notifies) => {
|
||||
//console.log('ob11 onGroupNotifiesUpdated', notifies[0]);
|
||||
if (![
|
||||
GroupNotifyTypes.ADMIN_SET,
|
||||
GroupNotifyTypes.ADMIN_UNSET,
|
||||
GroupNotifyTypes.ADMIN_UNSET_OTHER,
|
||||
].includes(notifies[0]?.type)) {
|
||||
for (const notify of notifies) {
|
||||
notify.time = Date.now();
|
||||
const notifyTime = parseInt(notify.seq) / 1000 / 1000;
|
||||
// log(`群通知时间${notifyTime}`, `启动时间${this.bootTime}`);
|
||||
if (notifyTime < this.bootTime) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const flag = notify.group.groupCode + '|' + notify.seq + '|' + notify.type;
|
||||
this.context.logger.logDebug('收到群通知', notify);
|
||||
|
||||
// let member2: GroupMember;
|
||||
// if (notify.user2.uid) {
|
||||
// member2 = await getGroupMember(notify.group.groupCode, null, notify.user2.uid);
|
||||
// }
|
||||
|
||||
if ([
|
||||
GroupNotifyTypes.ADMIN_SET,
|
||||
GroupNotifyTypes.ADMIN_UNSET,
|
||||
GroupNotifyTypes.ADMIN_UNSET_OTHER,
|
||||
].includes(notify.type)) {
|
||||
const member1 = await this.core.apis.GroupApi.getGroupMember(notify.group.groupCode, notify.user1.uid);
|
||||
this.context.logger.logDebug('有管理员变动通知');
|
||||
// refreshGroupMembers(notify.group.groupCode).then();
|
||||
|
||||
this.context.logger.logDebug('开始获取变动的管理员');
|
||||
if (member1) {
|
||||
this.context.logger.logDebug('变动管理员获取成功');
|
||||
// member1.role = notify.type == GroupNotifyTypes.ADMIN_SET ? GroupMemberRole.admin : GroupMemberRole.normal;
|
||||
|
||||
const groupAdminNoticeEvent = new OB11GroupAdminNoticeEvent(
|
||||
this.core,
|
||||
parseInt(notify.group.groupCode),
|
||||
parseInt(member1.uin),
|
||||
[GroupNotifyTypes.ADMIN_UNSET, GroupNotifyTypes.ADMIN_UNSET_OTHER].includes(notify.type) ? 'unset' : 'set',
|
||||
);
|
||||
this.networkManager.emitEvent(groupAdminNoticeEvent)
|
||||
.catch(e => this.context.logger.logError('处理群管理员变动失败', e));
|
||||
} else {
|
||||
this.context.logger.logDebug('获取群通知的成员信息失败', notify, this.core.apis.GroupApi.getGroup(notify.group.groupCode));
|
||||
}
|
||||
} else if (notify.type == GroupNotifyTypes.MEMBER_EXIT || notify.type == GroupNotifyTypes.KICK_MEMBER) {
|
||||
this.context.logger.logDebug('有成员退出通知', notify);
|
||||
const member1Uin = (await this.core.apis.UserApi.getUinByUidV2(notify.user1.uid))!;
|
||||
let operatorId = member1Uin;
|
||||
let subType: GroupDecreaseSubType = 'leave';
|
||||
if (notify.user2.uid) {
|
||||
// 是被踢的
|
||||
const member2Uin = await this.core.apis.UserApi.getUinByUidV2(notify.user2.uid);
|
||||
if (member2Uin) {
|
||||
operatorId = member2Uin;
|
||||
}
|
||||
subType = 'kick';
|
||||
}
|
||||
const groupDecreaseEvent = new OB11GroupDecreaseEvent(
|
||||
this.core,
|
||||
parseInt(notify.group.groupCode),
|
||||
parseInt(member1Uin),
|
||||
parseInt(operatorId),
|
||||
subType,
|
||||
);
|
||||
this.networkManager.emitEvent(groupDecreaseEvent)
|
||||
.catch(e => this.context.logger.logError('处理群成员退出失败', e));
|
||||
// notify.status == 1 表示未处理 2表示处理完成
|
||||
} else if ([
|
||||
GroupNotifyTypes.JOIN_REQUEST,
|
||||
].includes(notify.type) && notify.status == 1) {
|
||||
this.context.logger.logDebug('有加群请求');
|
||||
try {
|
||||
let requestUin = (await this.core.apis.UserApi.getUinByUidV2(notify.user1.uid))!;
|
||||
if (isNaN(parseInt(requestUin))) {
|
||||
requestUin = (await this.core.apis.UserApi.getUserDetailInfo(notify.user1.uid)).uin;
|
||||
}
|
||||
const groupRequestEvent = new OB11GroupRequestEvent(
|
||||
this.core,
|
||||
parseInt(notify.group.groupCode),
|
||||
parseInt(requestUin),
|
||||
'add',
|
||||
notify.postscript,
|
||||
flag,
|
||||
);
|
||||
this.networkManager.emitEvent(groupRequestEvent)
|
||||
.catch(e => this.context.logger.logError('处理加群请求失败', e));
|
||||
} catch (e) {
|
||||
this.context.logger.logError('获取加群人QQ号失败 Uid:', notify.user1.uid, e);
|
||||
}
|
||||
} else if (notify.type == GroupNotifyTypes.INVITE_ME) {
|
||||
this.context.logger.logDebug(`收到邀请我加群通知:${notify}`);
|
||||
const groupInviteEvent = new OB11GroupRequestEvent(
|
||||
this.core,
|
||||
parseInt(notify.group.groupCode),
|
||||
parseInt(notify.user1.uid),
|
||||
'invite',
|
||||
notify.postscript,
|
||||
flag,
|
||||
);
|
||||
this.networkManager.emitEvent(groupInviteEvent)
|
||||
.catch(e => this.context.logger.logError('处理邀请本人加群失败', e));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.context.session.getGroupService().addKernelGroupListener(
|
||||
new this.context.wrapper.NodeIKernelGroupListener(proxiedListenerOf(groupListener, this.context.logger)),
|
||||
);
|
||||
}
|
||||
|
||||
private async emitMsg(message: RawMessage) {
|
||||
const { debug, reportSelfMessage, messagePostFormat } = this.configLoader.configData;
|
||||
this.context.logger.logDebug('收到新消息', message);
|
||||
OB11Constructor.message(this.core, message, messagePostFormat).then((ob11Msg) => {
|
||||
this.context.logger.logDebug('收到消息: ', ob11Msg);
|
||||
if (debug) {
|
||||
ob11Msg.raw = message;
|
||||
} else {
|
||||
if (ob11Msg.message.length === 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
logOB11Message(this.core, ob11Msg)
|
||||
.catch(e => this.context.logger.logError('logMessage error: ', e));
|
||||
const isSelfMsg = ob11Msg.user_id.toString() == this.core.selfInfo.uin;
|
||||
if (isSelfMsg && !reportSelfMessage) {
|
||||
return;
|
||||
}
|
||||
if (isSelfMsg) {
|
||||
ob11Msg.target_id = parseInt(message.peerUin);
|
||||
}
|
||||
this.networkManager.emitEvent(ob11Msg);
|
||||
}).catch(e => this.context.logger.logError('constructMessage error: ', e));
|
||||
|
||||
OB11Constructor.GroupEvent(this.core, message).then(groupEvent => {
|
||||
if (groupEvent) {
|
||||
// log("post group event", groupEvent);
|
||||
this.networkManager.emitEvent(groupEvent);
|
||||
}
|
||||
}).catch(e => this.context.logger.logError('constructGroupEvent error: ', e));
|
||||
|
||||
OB11Constructor.PrivateEvent(this.core, message).then(privateEvent => {
|
||||
if (privateEvent) {
|
||||
// log("post private event", privateEvent);
|
||||
this.networkManager.emitEvent(privateEvent);
|
||||
}
|
||||
}).catch(e => this.context.logger.logError('constructPrivateEvent error: ', e));
|
||||
}
|
||||
|
||||
private async emitRecallMsg(msgList: RawMessage[]) {
|
||||
for (const message of msgList) {
|
||||
// log("message update", message.sendStatus, message.msgId, message.msgSeq)
|
||||
if (message.recallTime != '0') { //todo: 这个判断方法不太好,应该使用灰色消息元素来判断?
|
||||
// 撤回消息上报
|
||||
const oriMessageId = MessageUnique.getShortIdByMsgId(message.msgId);
|
||||
if (!oriMessageId) {
|
||||
continue;
|
||||
}
|
||||
if (message.chatType == ChatType.friend) {
|
||||
const friendRecallEvent = new OB11FriendRecallNoticeEvent(
|
||||
this.core,
|
||||
parseInt(message!.senderUin),
|
||||
oriMessageId,
|
||||
);
|
||||
this.networkManager.emitEvent(friendRecallEvent)
|
||||
.catch(e => this.context.logger.logError('处理好友消息撤回失败', e));
|
||||
} else if (message.chatType == ChatType.group) {
|
||||
let operatorId = message.senderUin;
|
||||
for (const element of message.elements) {
|
||||
const operatorUid = element.grayTipElement?.revokeElement.operatorUid;
|
||||
const operator = await this.core.apis.GroupApi.getGroupMember(message.peerUin, operatorUid);
|
||||
operatorId = operator?.uin || message.senderUin;
|
||||
}
|
||||
const groupRecallEvent = new OB11GroupRecallNoticeEvent(
|
||||
this.core,
|
||||
parseInt(message.peerUin),
|
||||
parseInt(message.senderUin),
|
||||
parseInt(operatorId),
|
||||
oriMessageId,
|
||||
);
|
||||
this.networkManager.emitEvent(groupRecallEvent)
|
||||
.catch(e => this.context.logger.logError('处理群消息撤回失败', e));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export * from './types';
|
||||
|
@ -1,400 +0,0 @@
|
||||
import {
|
||||
BuddyListener,
|
||||
BuddyReqType,
|
||||
ChatType,
|
||||
GroupListener,
|
||||
GroupNotifyTypes,
|
||||
InstanceContext,
|
||||
MsgListener,
|
||||
NapCatCore,
|
||||
RawMessage,
|
||||
} from '@/core';
|
||||
import { OB11Config, OB11ConfigLoader } from './helper/config';
|
||||
import { NapCatPathWrapper } from '@/common/framework/napcat';
|
||||
import { OneBotApiContextType } from '@/onebot/types';
|
||||
import { OneBotFriendApi, OneBotGroupApi, OneBotUserApi } from './api';
|
||||
import {
|
||||
OB11ActiveHttpAdapter,
|
||||
OB11ActiveWebSocketAdapter,
|
||||
OB11NetworkManager,
|
||||
OB11PassiveHttpAdapter,
|
||||
OB11PassiveWebSocketAdapter,
|
||||
} from '@/onebot/network';
|
||||
import { OB11InputStatusEvent } from '@/onebot/event/notice/OB11InputStatusEvent';
|
||||
import { MessageUnique } from '@/common/utils/MessageUnique';
|
||||
import { OB11Constructor } from '@/onebot/helper/data';
|
||||
import { logOB11Message } from '@/onebot/helper/log';
|
||||
import { proxiedListenerOf } from '@/common/utils/proxy-handler';
|
||||
import { createActionMap } from './action';
|
||||
import { WebUiDataRuntime } from '@/webui/src/helper/Data';
|
||||
import { OB11FriendRecallNoticeEvent } from '@/onebot/event/notice/OB11FriendRecallNoticeEvent';
|
||||
import { OB11GroupRecallNoticeEvent } from '@/onebot/event/notice/OB11GroupRecallNoticeEvent';
|
||||
import { OB11FriendRequestEvent } from '@/onebot/event/request/OB11FriendRequest';
|
||||
import { OB11GroupAdminNoticeEvent } from '@/onebot/event/notice/OB11GroupAdminNoticeEvent';
|
||||
import { GroupDecreaseSubType, OB11GroupDecreaseEvent } from '@/onebot/event/notice/OB11GroupDecreaseEvent';
|
||||
import { OB11GroupRequestEvent } from '@/onebot/event/request/OB11GroupRequest';
|
||||
|
||||
//OneBot实现类
|
||||
export class NapCatOneBot11Adapter {
|
||||
readonly core: NapCatCore;
|
||||
readonly context: InstanceContext;
|
||||
|
||||
configLoader: OB11ConfigLoader;
|
||||
apiContext: OneBotApiContextType;
|
||||
networkManager: OB11NetworkManager;
|
||||
|
||||
private bootTime = Date.now() / 1000;
|
||||
|
||||
constructor(core: NapCatCore, context: InstanceContext, pathWrapper: NapCatPathWrapper) {
|
||||
this.core = core;
|
||||
this.context = context;
|
||||
this.configLoader = new OB11ConfigLoader(core, pathWrapper.configPath);
|
||||
this.apiContext = {
|
||||
GroupApi: new OneBotGroupApi(this, core),
|
||||
UserApi: new OneBotUserApi(this, core),
|
||||
FriendApi: new OneBotFriendApi(this, core),
|
||||
};
|
||||
this.networkManager = new OB11NetworkManager();
|
||||
this.InitOneBot().then().catch(e => this.context.logger.logError('初始化OneBot失败', e));
|
||||
}
|
||||
|
||||
async InitOneBot() {
|
||||
const NTQQUserApi = this.core.apis.UserApi;
|
||||
const selfInfo = this.core.selfInfo;
|
||||
const ob11Config = this.configLoader.configData;
|
||||
|
||||
const serviceInfo = `
|
||||
HTTP服务 ${ob11Config.http.enable ? '已启动' : '未启动'}, ${ob11Config.http.host}:${ob11Config.http.port}
|
||||
HTTP上报服务 ${ob11Config.http.enablePost ? '已启动' : '未启动'}, 上报地址: ${ob11Config.http.postUrls}
|
||||
WebSocket服务 ${ob11Config.ws.enable ? '已启动' : '未启动'}, ${ob11Config.ws.host}:${ob11Config.ws.port}
|
||||
WebSocket反向服务 ${ob11Config.reverseWs.enable ? '已启动' : '未启动'}, 反向地址: ${ob11Config.reverseWs.urls}`;
|
||||
|
||||
NTQQUserApi.getUserDetailInfo(selfInfo.uid).then(user => {
|
||||
selfInfo.nick = user.nick;
|
||||
this.context.logger.setLogSelfInfo(selfInfo);
|
||||
}).catch(this.context.logger.logError);
|
||||
this.context.logger.log(`[Notice] [OneBot11] ${serviceInfo}`);
|
||||
|
||||
//创建NetWork服务
|
||||
const actions = createActionMap(this, this.core);
|
||||
if (ob11Config.http.enable) {
|
||||
await this.networkManager.registerAdapter(new OB11PassiveHttpAdapter(
|
||||
ob11Config.http.port, ob11Config.token, this.core, this
|
||||
));
|
||||
}
|
||||
if (ob11Config.http.enablePost) {
|
||||
ob11Config.http.postUrls.forEach(url => {
|
||||
this.networkManager.registerAdapter(new OB11ActiveHttpAdapter(
|
||||
url, ob11Config.heartInterval, ob11Config.token, this.core, this
|
||||
));
|
||||
});
|
||||
}
|
||||
if (ob11Config.ws.enable) {
|
||||
const OBPassiveWebSocketAdapter = new OB11PassiveWebSocketAdapter(
|
||||
ob11Config.ws.host, ob11Config.ws.port, ob11Config.heartInterval, ob11Config.token, this.core, this
|
||||
);
|
||||
await this.networkManager.registerAdapter(OBPassiveWebSocketAdapter);
|
||||
}
|
||||
if (ob11Config.reverseWs.enable) {
|
||||
ob11Config.reverseWs.urls.forEach(url => {
|
||||
this.networkManager.registerAdapter(new OB11ActiveWebSocketAdapter(
|
||||
url, 5000, ob11Config.heartInterval, ob11Config.token, this.core, this
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
await this.networkManager.registerAllActions(actions);
|
||||
await this.networkManager.openAllAdapters();
|
||||
|
||||
this.initMsgListener();
|
||||
this.initBuddyListener();
|
||||
this.initGroupListener();
|
||||
|
||||
await WebUiDataRuntime.setQQLoginUin(selfInfo.uin.toString());
|
||||
await WebUiDataRuntime.setQQLoginStatus(true);
|
||||
await WebUiDataRuntime.setOB11ConfigCall(async (ob11: OB11Config) => {
|
||||
this.configLoader.save(ob11);
|
||||
});
|
||||
}
|
||||
|
||||
private initMsgListener() {
|
||||
const msgListener = new MsgListener();
|
||||
|
||||
msgListener.onInputStatusPush = async data => {
|
||||
const uin = await this.core.apis.UserApi.getUinByUidV2(data.fromUin);
|
||||
this.context.logger.log(`[Notice] [输入状态] ${uin} ${data.statusText}`);
|
||||
await this.networkManager.emitEvent(new OB11InputStatusEvent(
|
||||
this.core,
|
||||
parseInt(uin),
|
||||
data.eventType,
|
||||
data.statusText
|
||||
));
|
||||
};
|
||||
|
||||
msgListener.onRecvMsg = async msg => {
|
||||
for (const m of msg) {
|
||||
if (this.bootTime > parseInt(m.msgTime)) {
|
||||
this.context.logger.logDebug(`消息时间${m.msgTime}早于启动时间${this.bootTime},忽略上报`);
|
||||
continue;
|
||||
}
|
||||
m.id = MessageUnique.createMsg(
|
||||
{
|
||||
chatType: m.chatType,
|
||||
peerUid: m.peerUid,
|
||||
guildId: ''
|
||||
},
|
||||
m.msgId
|
||||
);
|
||||
await this.emitMsg(m)
|
||||
.catch(e => this.context.logger.logError('处理消息失败', e));
|
||||
}
|
||||
};
|
||||
|
||||
msgListener.onMsgInfoListUpdate = async msgList => {
|
||||
this.emitRecallMsg(msgList)
|
||||
.catch(e => this.context.logger.logError('处理消息失败', e));
|
||||
for (const msg of msgList.filter(e => e.senderUin == this.core.selfInfo.uin)) {
|
||||
// console.log(msg);
|
||||
if (msg.sendStatus == 2) {
|
||||
// 完成后再post
|
||||
OB11Constructor.message(this.core, msg, this.configLoader.configData.messagePostFormat)
|
||||
.then((ob11Msg) => {
|
||||
ob11Msg.target_id = parseInt(msg.peerUin);
|
||||
if (this.configLoader.configData.reportSelfMessage) {
|
||||
msg.id = MessageUnique.createMsg({ chatType: msg.chatType, peerUid: msg.peerUid, guildId: '' }, msg.msgId);
|
||||
this.emitMsg(msg);
|
||||
} else {
|
||||
logOB11Message(this.core, ob11Msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.context.session.getMsgService().addKernelMsgListener(
|
||||
new this.context.wrapper.NodeIKernelMsgListener(proxiedListenerOf(msgListener, this.context.logger)),
|
||||
);
|
||||
}
|
||||
|
||||
private initBuddyListener() {
|
||||
const buddyListener = new BuddyListener();
|
||||
|
||||
buddyListener.onBuddyReqChange = reqs => {
|
||||
reqs.buddyReqs.forEach(async req => {
|
||||
if (!!req.isInitiator || (req.isDecide && req.reqType !== BuddyReqType.KMEINITIATORWAITPEERCONFIRM)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const requesterUin = await this.core.apis.UserApi.getUinByUidV2(req.friendUid);
|
||||
await this.networkManager.emitEvent(new OB11FriendRequestEvent(
|
||||
this.core,
|
||||
parseInt(requesterUin!),
|
||||
req.friendUid + '|' + req.reqTime,
|
||||
req.extWords
|
||||
));
|
||||
} catch (e) {
|
||||
this.context.logger.logDebug('获取加好友者QQ号失败', e);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
this.context.session.getBuddyService().addKernelBuddyListener(
|
||||
new this.context.wrapper.NodeIKernelBuddyListener(proxiedListenerOf(buddyListener, this.context.logger)),
|
||||
);
|
||||
}
|
||||
|
||||
private initGroupListener() {
|
||||
const groupListener = new GroupListener();
|
||||
|
||||
groupListener.onGroupNotifiesUpdated = async (_, notifies) => {
|
||||
//console.log('ob11 onGroupNotifiesUpdated', notifies[0]);
|
||||
if (![
|
||||
GroupNotifyTypes.ADMIN_SET,
|
||||
GroupNotifyTypes.ADMIN_UNSET,
|
||||
GroupNotifyTypes.ADMIN_UNSET_OTHER
|
||||
].includes(notifies[0]?.type)) {
|
||||
for (const notify of notifies) {
|
||||
notify.time = Date.now();
|
||||
const notifyTime = parseInt(notify.seq) / 1000 / 1000;
|
||||
// log(`群通知时间${notifyTime}`, `启动时间${this.bootTime}`);
|
||||
if (notifyTime < this.bootTime) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const flag = notify.group.groupCode + '|' + notify.seq + '|' + notify.type;
|
||||
this.context.logger.logDebug('收到群通知', notify);
|
||||
|
||||
// let member2: GroupMember;
|
||||
// if (notify.user2.uid) {
|
||||
// member2 = await getGroupMember(notify.group.groupCode, null, notify.user2.uid);
|
||||
// }
|
||||
|
||||
if ([
|
||||
GroupNotifyTypes.ADMIN_SET,
|
||||
GroupNotifyTypes.ADMIN_UNSET,
|
||||
GroupNotifyTypes.ADMIN_UNSET_OTHER
|
||||
].includes(notify.type)) {
|
||||
const member1 = await this.core.apis.GroupApi.getGroupMember(notify.group.groupCode, notify.user1.uid);
|
||||
this.context.logger.logDebug('有管理员变动通知');
|
||||
// refreshGroupMembers(notify.group.groupCode).then();
|
||||
|
||||
this.context.logger.logDebug('开始获取变动的管理员');
|
||||
if (member1) {
|
||||
this.context.logger.logDebug('变动管理员获取成功');
|
||||
// member1.role = notify.type == GroupNotifyTypes.ADMIN_SET ? GroupMemberRole.admin : GroupMemberRole.normal;
|
||||
|
||||
const groupAdminNoticeEvent = new OB11GroupAdminNoticeEvent(
|
||||
this.core,
|
||||
parseInt(notify.group.groupCode),
|
||||
parseInt(member1.uin),
|
||||
[GroupNotifyTypes.ADMIN_UNSET, GroupNotifyTypes.ADMIN_UNSET_OTHER].includes(notify.type) ? 'unset' : 'set'
|
||||
);
|
||||
this.networkManager.emitEvent(groupAdminNoticeEvent)
|
||||
.catch(e => this.context.logger.logError('处理群管理员变动失败', e));
|
||||
} else {
|
||||
this.context.logger.logDebug('获取群通知的成员信息失败', notify, this.core.apis.GroupApi.getGroup(notify.group.groupCode));
|
||||
}
|
||||
} else if (notify.type == GroupNotifyTypes.MEMBER_EXIT || notify.type == GroupNotifyTypes.KICK_MEMBER) {
|
||||
this.context.logger.logDebug('有成员退出通知', notify);
|
||||
const member1Uin = (await this.core.apis.UserApi.getUinByUidV2(notify.user1.uid))!;
|
||||
let operatorId = member1Uin;
|
||||
let subType: GroupDecreaseSubType = 'leave';
|
||||
if (notify.user2.uid) {
|
||||
// 是被踢的
|
||||
const member2Uin = await this.core.apis.UserApi.getUinByUidV2(notify.user2.uid);
|
||||
if (member2Uin) {
|
||||
operatorId = member2Uin;
|
||||
}
|
||||
subType = 'kick';
|
||||
}
|
||||
const groupDecreaseEvent = new OB11GroupDecreaseEvent(
|
||||
this.core,
|
||||
parseInt(notify.group.groupCode),
|
||||
parseInt(member1Uin),
|
||||
parseInt(operatorId),
|
||||
subType
|
||||
);
|
||||
this.networkManager.emitEvent(groupDecreaseEvent)
|
||||
.catch(e => this.context.logger.logError('处理群成员退出失败', e));
|
||||
// notify.status == 1 表示未处理 2表示处理完成
|
||||
} else if ([
|
||||
GroupNotifyTypes.JOIN_REQUEST
|
||||
].includes(notify.type) && notify.status == 1) {
|
||||
this.context.logger.logDebug('有加群请求');
|
||||
try {
|
||||
let requestUin = (await this.core.apis.UserApi.getUinByUidV2(notify.user1.uid))!;
|
||||
if (isNaN(parseInt(requestUin))) {
|
||||
requestUin = (await this.core.apis.UserApi.getUserDetailInfo(notify.user1.uid)).uin;
|
||||
}
|
||||
const groupRequestEvent = new OB11GroupRequestEvent(
|
||||
this.core,
|
||||
parseInt(notify.group.groupCode),
|
||||
parseInt(requestUin),
|
||||
'add',
|
||||
notify.postscript,
|
||||
flag
|
||||
);
|
||||
this.networkManager.emitEvent(groupRequestEvent)
|
||||
.catch(e => this.context.logger.logError('处理加群请求失败', e));
|
||||
} catch (e) {
|
||||
this.context.logger.logError('获取加群人QQ号失败 Uid:', notify.user1.uid, e);
|
||||
}
|
||||
} else if (notify.type == GroupNotifyTypes.INVITE_ME) {
|
||||
this.context.logger.logDebug(`收到邀请我加群通知:${notify}`);
|
||||
const groupInviteEvent = new OB11GroupRequestEvent(
|
||||
this.core,
|
||||
parseInt(notify.group.groupCode),
|
||||
parseInt(notify.user1.uid),
|
||||
'invite',
|
||||
notify.postscript,
|
||||
flag
|
||||
);
|
||||
this.networkManager.emitEvent(groupInviteEvent)
|
||||
.catch(e => this.context.logger.logError('处理邀请本人加群失败', e));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.context.session.getGroupService().addKernelGroupListener(
|
||||
new this.context.wrapper.NodeIKernelGroupListener(proxiedListenerOf(groupListener, this.context.logger)),
|
||||
);
|
||||
}
|
||||
|
||||
private async emitMsg(message: RawMessage) {
|
||||
const { debug, reportSelfMessage, messagePostFormat } = this.configLoader.configData;
|
||||
this.context.logger.logDebug('收到新消息', message);
|
||||
OB11Constructor.message(this.core, message, messagePostFormat).then((ob11Msg) => {
|
||||
this.context.logger.logDebug('收到消息: ', ob11Msg);
|
||||
if (debug) {
|
||||
ob11Msg.raw = message;
|
||||
} else {
|
||||
if (ob11Msg.message.length === 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
logOB11Message(this.core, ob11Msg)
|
||||
.catch(e => this.context.logger.logError('logMessage error: ', e));
|
||||
const isSelfMsg = ob11Msg.user_id.toString() == this.core.selfInfo.uin;
|
||||
if (isSelfMsg && !reportSelfMessage) {
|
||||
return;
|
||||
}
|
||||
if (isSelfMsg) {
|
||||
ob11Msg.target_id = parseInt(message.peerUin);
|
||||
}
|
||||
this.networkManager.emitEvent(ob11Msg);
|
||||
}).catch(e => this.context.logger.logError('constructMessage error: ', e));
|
||||
|
||||
OB11Constructor.GroupEvent(this.core, message).then(groupEvent => {
|
||||
if (groupEvent) {
|
||||
// log("post group event", groupEvent);
|
||||
this.networkManager.emitEvent(groupEvent);
|
||||
}
|
||||
}).catch(e => this.context.logger.logError('constructGroupEvent error: ', e));
|
||||
|
||||
OB11Constructor.PrivateEvent(this.core, message).then(privateEvent => {
|
||||
if (privateEvent) {
|
||||
// log("post private event", privateEvent);
|
||||
this.networkManager.emitEvent(privateEvent);
|
||||
}
|
||||
}).catch(e => this.context.logger.logError('constructPrivateEvent error: ', e));
|
||||
}
|
||||
|
||||
private async emitRecallMsg(msgList: RawMessage[]) {
|
||||
for (const message of msgList) {
|
||||
// log("message update", message.sendStatus, message.msgId, message.msgSeq)
|
||||
if (message.recallTime != '0') { //todo: 这个判断方法不太好,应该使用灰色消息元素来判断?
|
||||
// 撤回消息上报
|
||||
const oriMessageId = MessageUnique.getShortIdByMsgId(message.msgId);
|
||||
if (!oriMessageId) {
|
||||
continue;
|
||||
}
|
||||
if (message.chatType == ChatType.friend) {
|
||||
const friendRecallEvent = new OB11FriendRecallNoticeEvent(
|
||||
this.core,
|
||||
parseInt(message!.senderUin),
|
||||
oriMessageId
|
||||
);
|
||||
this.networkManager.emitEvent(friendRecallEvent)
|
||||
.catch(e => this.context.logger.logError('处理好友消息撤回失败', e));
|
||||
} else if (message.chatType == ChatType.group) {
|
||||
let operatorId = message.senderUin;
|
||||
for (const element of message.elements) {
|
||||
const operatorUid = element.grayTipElement?.revokeElement.operatorUid;
|
||||
const operator = await this.core.apis.GroupApi.getGroupMember(message.peerUin, operatorUid);
|
||||
operatorId = operator?.uin || message.senderUin;
|
||||
}
|
||||
const groupRecallEvent = new OB11GroupRecallNoticeEvent(
|
||||
this.core,
|
||||
parseInt(message.peerUin),
|
||||
parseInt(message.senderUin),
|
||||
parseInt(operatorId),
|
||||
oriMessageId
|
||||
);
|
||||
this.networkManager.emitEvent(groupRecallEvent)
|
||||
.catch(e => this.context.logger.logError('处理群消息撤回失败', e));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -4,8 +4,8 @@ import { createHmac } from 'crypto';
|
||||
import { LogWrapper } from '@/common/utils/log';
|
||||
import { QuickAction, QuickActionEvent } from '../types';
|
||||
import { NapCatCore } from '@/core';
|
||||
import { NapCatOneBot11Adapter } from '../main';
|
||||
import { handleQuickOperation } from '../helper/quick';
|
||||
import { NapCatOneBot11Adapter } from '@/onebot';
|
||||
|
||||
export class OB11ActiveHttpAdapter implements IOB11NetworkAdapter {
|
||||
url: string;
|
||||
|
@ -3,10 +3,10 @@ import { WebSocket } from 'ws';
|
||||
import BaseAction from '@/onebot/action/BaseAction';
|
||||
import { OB11HeartbeatEvent } from '../event/meta/OB11HeartbeatEvent';
|
||||
import { NapCatCore } from '@/core';
|
||||
import { NapCatOneBot11Adapter } from '../main';
|
||||
import { ActionName } from '@/onebot/action/types';
|
||||
import { OB11Response } from '@/onebot/action/OB11Response';
|
||||
import { LogWrapper } from '@/common/utils/log';
|
||||
import { NapCatOneBot11Adapter } from '@/onebot';
|
||||
|
||||
export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
|
||||
url: string;
|
||||
|
@ -3,8 +3,8 @@ import BaseAction from '@/onebot/action/BaseAction';
|
||||
import express, { Express, Request, Response } from 'express';
|
||||
import http from 'http';
|
||||
import { NapCatCore } from '@/core';
|
||||
import { NapCatOneBot11Adapter } from '../main';
|
||||
import { OB11Response } from '../action/OB11Response';
|
||||
import { NapCatOneBot11Adapter } from '@/onebot';
|
||||
|
||||
export class OB11PassiveHttpAdapter implements IOB11NetworkAdapter {
|
||||
token: string;
|
||||
|
Loading…
x
Reference in New Issue
Block a user