feat: 迁移事件解析原理

This commit is contained in:
手瓜一十雪
2024-12-03 19:28:51 +08:00
parent 39c3af7ff3
commit 3fa153cdc7
6 changed files with 175 additions and 377 deletions

View File

@@ -139,14 +139,21 @@ export class NTQQGroupApi {
async getGroupMemberAll(groupCode: string, forced = false) {
return this.context.session.getGroupService().getAllMemberList(groupCode, forced);
}
async refreshGroupMemberCache(groupCode: string) {
try {
const members = await this.getGroupMemberAll(groupCode, true);
this.groupMemberCache.set(groupCode, members.result.infos);
} catch (e) {
this.context.logger.logError(`刷新群成员缓存失败, ${e}`);
}
}
async getGroupMember(groupCode: string | number, memberUinOrUid: string | number) {
const groupCodeStr = groupCode.toString();
const memberUinOrUidStr = memberUinOrUid.toString();
let members = this.groupMemberCache.get(groupCodeStr);
if (!members) {
try {
members = await this.getGroupMembers(groupCodeStr);
members = (await this.getGroupMemberAll(groupCodeStr)).result.infos;
this.groupMemberCache.set(groupCodeStr, members);
} catch (e) {
return null;
@@ -164,7 +171,7 @@ export class NTQQGroupApi {
let member = getMember();
if (!member) {
members = await this.getGroupMembers(groupCodeStr);
members = members = (await this.getGroupMemberAll(groupCodeStr)).result.infos;
member = getMember();
}
return member;
@@ -253,28 +260,28 @@ export class NTQQGroupApi {
return notifies;
}
async getGroupMemberV2(GroupCode: string, uid: string, forced = false) {
const Listener = this.core.eventWrapper.registerListen(
'NodeIKernelGroupListener/onMemberInfoChange',
(params, _, members) => params === GroupCode && members.size > 0,
1,
forced ? 5000 : 250,
);
const retData = await (
this.core.eventWrapper
.createEventFunction('NodeIKernelGroupService/getMemberInfo')
)!(GroupCode, [uid], forced);
if (retData.result !== 0) {
throw new Error(`${retData.errMsg}`);
}
const result = await Listener as unknown;
let member: GroupMember | undefined;
if (Array.isArray(result) && result?.[2] instanceof Map) {
const members = result[2] as Map<string, GroupMember>;
member = members.get(uid);
}
return member;
}
// async getGroupMemberV2(GroupCode: string, uid: string, forced = false) {
// const Listener = this.core.eventWrapper.registerListen(
// 'NodeIKernelGroupListener/onMemberInfoChange',
// (params, _, members) => params === GroupCode && members.size > 0,
// 1,
// forced ? 5000 : 250,
// );
// const retData = await (
// this.core.eventWrapper
// .createEventFunction('NodeIKernelGroupService/getMemberInfo')
// )!(GroupCode, [uid], forced);
// if (retData.result !== 0) {
// throw new Error(`${retData.errMsg}`);
// }
// const result = await Listener as unknown;
// let member: GroupMember | undefined;
// if (Array.isArray(result) && result?.[2] instanceof Map) {
// const members = result[2] as Map<string, GroupMember>;
// member = members.get(uid);
// }
// return member;
// }
async searchGroup(groupCode: string) {
const [, ret] = await this.core.eventWrapper.callNormalEventV2(
@@ -316,88 +323,88 @@ export class NTQQGroupApi {
return undefined;
}
async tryGetGroupMembersV2(groupQQ: string, modeListener = false, num = 30, timeout = 100): Promise<{
infos: Map<string, GroupMember>;
finish: boolean;
hasNext: boolean | undefined;
}> {
const sceneId = this.context.session.getGroupService().createMemberListScene(groupQQ, 'groupMemberList_MainWindow_1');
const once = this.core.eventWrapper.registerListen('NodeIKernelGroupListener/onMemberListChange', (params) => params.sceneId === sceneId, 0, timeout)
.catch(() => { });
const result = await this.context.session.getGroupService().getNextMemberList(sceneId, undefined, num);
if (result.errCode !== 0) {
throw new Error('获取群成员列表出错,' + result.errMsg);
}
let resMode2;
if (modeListener) {
const ret = (await once)?.[0];
if (ret) {
resMode2 = ret;
}
}
this.context.session.getGroupService().destroyMemberListScene(sceneId);
return {
infos: new Map([...(resMode2?.infos ?? []), ...result.result.infos]),
finish: result.result.finish,
hasNext: resMode2?.hasNext,
};
}
// async tryGetGroupMembersV2(groupQQ: string, modeListener = false, num = 30, timeout = 100): Promise<{
// infos: Map<string, GroupMember>;
// finish: boolean;
// hasNext: boolean | undefined;
// }> {
// const sceneId = this.context.session.getGroupService().createMemberListScene(groupQQ, 'groupMemberList_MainWindow_1');
// const once = this.core.eventWrapper.registerListen('NodeIKernelGroupListener/onMemberListChange', (params) => params.sceneId === sceneId, 0, timeout)
// .catch(() => { });
// const result = await this.context.session.getGroupService().getNextMemberList(sceneId, undefined, num);
// if (result.errCode !== 0) {
// throw new Error('获取群成员列表出错,' + result.errMsg);
// }
// let resMode2;
// if (modeListener) {
// const ret = (await once)?.[0];
// if (ret) {
// resMode2 = ret;
// }
// }
// this.context.session.getGroupService().destroyMemberListScene(sceneId);
// return {
// infos: new Map([...(resMode2?.infos ?? []), ...result.result.infos]),
// finish: result.result.finish,
// hasNext: resMode2?.hasNext,
// };
// }
async GetGroupMembersV3(groupQQ: string, num = 3000, timeout = 2500): Promise<{
infos: Map<string, GroupMember>;
finish: boolean;
hasNext: boolean | undefined;
listenerMode: boolean;
}> {
const sceneId = this.context.session.getGroupService().createMemberListScene(groupQQ, 'groupMemberList_MainWindow_1');
const once = this.core.eventWrapper.registerListen('NodeIKernelGroupListener/onMemberListChange', (params) => params.sceneId === sceneId, 0, timeout)
.catch(() => { });
const result = await this.context.session.getGroupService().getNextMemberList(sceneId, undefined, num);
if (result.errCode !== 0) {
throw new Error('获取群成员列表出错,' + result.errMsg);
}
let resMode2;
if (result.result.finish && result.result.infos.size === 0) {
const ret = (await once)?.[0];
if (ret) {
resMode2 = ret;
}
}
this.context.session.getGroupService().destroyMemberListScene(sceneId);
return {
infos: new Map([...(resMode2?.infos ?? []), ...result.result.infos]),
finish: result.result.finish,
hasNext: resMode2?.hasNext,
listenerMode: resMode2?.hasNext !== undefined
};
}
// async GetGroupMembersV3(groupQQ: string, num = 3000, timeout = 2500): Promise<{
// infos: Map<string, GroupMember>;
// finish: boolean;
// hasNext: boolean | undefined;
// listenerMode: boolean;
// }> {
// const sceneId = this.context.session.getGroupService().createMemberListScene(groupQQ, 'groupMemberList_MainWindow_1');
// const once = this.core.eventWrapper.registerListen('NodeIKernelGroupListener/onMemberListChange', (params) => params.sceneId === sceneId, 0, timeout)
// .catch(() => { });
// const result = await this.context.session.getGroupService().getNextMemberList(sceneId, undefined, num);
// if (result.errCode !== 0) {
// throw new Error('获取群成员列表出错,' + result.errMsg);
// }
// let resMode2;
// if (result.result.finish && result.result.infos.size === 0) {
// const ret = (await once)?.[0];
// if (ret) {
// resMode2 = ret;
// }
// }
// this.context.session.getGroupService().destroyMemberListScene(sceneId);
// return {
// infos: new Map([...(resMode2?.infos ?? []), ...result.result.infos]),
// finish: result.result.finish,
// hasNext: resMode2?.hasNext,
// listenerMode: resMode2?.hasNext !== undefined
// };
// }
async getGroupMembersV2(groupQQ: string, num = 3000, no_cache: boolean = false): Promise<Map<string, GroupMember>> {
if (no_cache) {
return (await this.getGroupMemberAll(groupQQ, true)).result.infos;
}
let res = await this.GetGroupMembersV3(groupQQ, num);
let ret = res.infos;
if (res.infos.size === 0 && !res.listenerMode) {
res = await this.GetGroupMembersV3(groupQQ, num);
ret = res.infos;
}
if (res.infos.size === 0) {
ret = (await this.getGroupMemberAll(groupQQ)).result.infos;
}
return ret;
}
// async getGroupMembersV2(groupQQ: string, num = 3000, no_cache: boolean = false): Promise<Map<string, GroupMember>> {
// if (no_cache) {
// return (await this.getGroupMemberAll(groupQQ, true)).result.infos;
// }
// let res = await this.GetGroupMembersV3(groupQQ, num);
// let ret = res.infos;
// if (res.infos.size === 0 && !res.listenerMode) {
// res = await this.GetGroupMembersV3(groupQQ, num);
// ret = res.infos;
// }
// if (res.infos.size === 0) {
// ret = (await this.getGroupMemberAll(groupQQ)).result.infos;
// }
// return ret;
// }
async getGroupMembers(groupQQ: string, num = 3000): Promise<Map<string, GroupMember>> {
const groupService = this.context.session.getGroupService();
const sceneId = groupService.createMemberListScene(groupQQ, 'groupMemberList_MainWindow');
const result = await groupService.getNextMemberList(sceneId, undefined, num);
if (result.errCode !== 0) {
throw new Error('获取群成员列表出错,' + result.errMsg);
}
this.context.logger.logDebug(`获取群(${groupQQ})成员列表结果:`, `members: ${result.result.infos.size}`);
return result.result.infos;
}
// async getGroupMembers(groupQQ: string, num = 3000): Promise<Map<string, GroupMember>> {
// const groupService = this.context.session.getGroupService();
// const sceneId = groupService.createMemberListScene(groupQQ, 'groupMemberList_MainWindow');
// const result = await groupService.getNextMemberList(sceneId, undefined, num);
// if (result.errCode !== 0) {
// throw new Error('获取群成员列表出错,' + result.errMsg);
// }
// this.context.logger.logDebug(`获取群(${groupQQ})成员列表结果:`, `members: ${result.result.infos.size}`);
// return result.result.infos;
// }
async getGroupFileCount(group_ids: Array<string>) {
return this.context.session.getRichMediaService().batchGetGroupFileCount(group_ids);

View File

@@ -24,10 +24,10 @@ import path from 'node:path';
import fs from 'node:fs';
import { hostname, systemName, systemVersion } from '@/common/system';
import { NTEventWrapper } from '@/common/event';
import { DataSource, GroupMember, KickedOffLineInfo, SelfInfo, SelfStatusInfo } from '@/core/types';
import { GroupMember, KickedOffLineInfo, SelfInfo, SelfStatusInfo } from '@/core/types';
import { NapCatConfigLoader } from '@/core/helper/config';
import os from 'node:os';
import { NodeIKernelGroupListener, NodeIKernelMsgListener, NodeIKernelProfileListener } from '@/core/listeners';
import { NodeIKernelMsgListener, NodeIKernelProfileListener } from '@/core/listeners';
import { proxiedListenerOf } from '@/common/proxy-handler';
import { NTQQPacketApi } from './apis/packet';
export * from './wrapper';
@@ -163,7 +163,6 @@ export class NapCatCore {
msgListener.onAddSendMsg = (msg) => {
this.context.logger.logMessage(msg, this.selfInfo);
};
//await sleep(2500);
this.context.session.getMsgService().addKernelMsgListener(
proxiedListenerOf(msgListener, this.context.logger),
);
@@ -185,92 +184,6 @@ export class NapCatCore {
this.context.session.getProfileService().addKernelProfileListener(
proxiedListenerOf(profileListener, this.context.logger),
);
// 群相关
const groupListener = new NodeIKernelGroupListener();
groupListener.onGroupListUpdate = (updateType, groupList) => {
// console.log("onGroupListUpdate", updateType, groupList)
groupList.map(g => {
const existGroup = this.apis.GroupApi.groupCache.get(g.groupCode);
//群成员数量变化 应该刷新缓存
if (existGroup && g.memberCount === existGroup.memberCount) {
Object.assign(existGroup, g);
} else {
this.apis.GroupApi.groupCache.set(g.groupCode, g);
// 获取群成员
}
const sceneId = this.context.session.getGroupService().createMemberListScene(g.groupCode, 'groupMemberList_MainWindow');
this.context.session.getGroupService().getNextMemberList(sceneId, undefined, 3000).then( /* r => {
// console.log(`get group ${g.groupCode} members`, r);
// r.result.infos.forEach(member => {
// });
// groupMembers.set(g.groupCode, r.result.infos);
} */);
this.context.session.getGroupService().destroyMemberListScene(sceneId);
});
};
groupListener.onMemberListChange = (arg) => {
// TODO: 应该加一个内部自己维护的成员变动callback用于判断成员变化通知
const groupCode = arg.sceneId.split('_')[0];
if (this.apis.GroupApi.groupMemberCache.has(groupCode)) {
const existMembers = this.apis.GroupApi.groupMemberCache.get(groupCode)!;
arg.infos.forEach((member, uid) => {
//console.log('onMemberListChange', member);
const existMember = existMembers.get(uid);
if (existMember) {
Object.assign(existMember, member);
} else {
existMembers.set(uid, member);
}
//移除成员
if (member.isDelete) {
existMembers.delete(uid);
}
});
} else {
this.apis.GroupApi.groupMemberCache.set(groupCode, arg.infos);
}
};
groupListener.onMemberInfoChange = (groupCode, dataSource, members) => {
if (dataSource === DataSource.LOCAL && members.get(this.selfInfo.uid)?.isDelete) {
// 自身退群或者被踢退群 5s用于Api操作 之后不再出现
setTimeout(() => {
this.apis.GroupApi.groupCache.delete(groupCode);
}, 5000);
}
const existMembers = this.apis.GroupApi.groupMemberCache.get(groupCode);
if (existMembers) {
members.forEach((member, uid) => {
const existMember = existMembers.get(uid);
if (existMember) {
// 检查管理变动
member.isChangeRole = this.checkAdminEvent(groupCode, member, existMember);
// 更新成员信息
Object.assign(existMember, member);
} else {
existMembers.set(uid, member);
}
//移除成员
if (member.isDelete) {
existMembers.delete(uid);
}
});
} else {
this.apis.GroupApi.groupMemberCache.set(groupCode, members);
}
};
this.context.session.getGroupService().addKernelGroupListener(
proxiedListenerOf(groupListener, this.context.logger),
);
}
checkAdminEvent(groupCode: string, memberNew: GroupMember, memberOld: GroupMember | undefined): boolean {
if (memberNew.role !== memberOld?.role) {
this.context.logger.logDebug(`${groupCode} ${memberNew.nick} 角色变更为 ${memberNew.role === 3 ? '管理员' : '群员'}`);
return true;
}
return false;
}
}