diff --git a/src/core/apis/group.ts b/src/core/apis/group.ts index ad5fe254..7b1ed692 100644 --- a/src/core/apis/group.ts +++ b/src/core/apis/group.ts @@ -18,6 +18,7 @@ export class NTQQGroupApi { context: InstanceContext; core: NapCatCore; groupMemberCache: Map> = new Map>(); + groupMemberCacheEvent: Map = new Map(); essenceLRU = new LimitedHashTable(1000); constructor(context: InstanceContext, core: NapCatCore) { @@ -44,7 +45,7 @@ export class NTQQGroupApi { async initCache() { for (const group of await this.getGroups(true)) { - this.refreshGroupMemberCache(group.groupCode).then().catch(); + this.refreshGroupMemberCache(group.groupCode, false).then().catch(e => this.context.logger.logError(e)); } } @@ -126,14 +127,26 @@ export class NTQQGroupApi { 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(`刷新群成员缓存失败, 群号: ${groupCode}, 错误: ${e}`); + async refreshGroupMemberCache(groupCode: string, isWait = true) { + this.groupMemberCacheEvent.set(groupCode, true); + const updateCache = async () => { + try { + const members = await this.getGroupMemberAll(groupCode, true); + this.groupMemberCache.set(groupCode, members.result.infos); + } catch (e) { + this.context.logger.logError(`刷新群成员缓存失败, 群号: ${groupCode}, 错误: ${e}`); + } finally { + this.groupMemberCacheEvent.set(groupCode, false); + } + }; + + if (isWait) { + await updateCache(); + } else { + updateCache(); } - return this.groupMemberCache; + + return this.groupMemberCache.get(groupCode); } async getGroupMember(groupCode: string | number, memberUinOrUid: string | number) { @@ -143,7 +156,7 @@ export class NTQQGroupApi { // 获取群成员缓存 let members = this.groupMemberCache.get(groupCodeStr); if (!members) { - members = (await this.refreshGroupMemberCache(groupCodeStr)).get(groupCodeStr); + members = (await this.refreshGroupMemberCache(groupCodeStr, true)); } const getMember = () => { @@ -157,7 +170,7 @@ export class NTQQGroupApi { let member = getMember(); // 如果缓存中不存在该成员,尝试刷新缓存 if (!member) { - members = (await this.refreshGroupMemberCache(groupCodeStr)).get(groupCodeStr); + members = (await this.refreshGroupMemberCache(groupCodeStr, true)); member = getMember(); } return member; diff --git a/src/onebot/action/group/GetGroupMemberInfo.ts b/src/onebot/action/group/GetGroupMemberInfo.ts index 3fc23a7e..d1e3d49d 100644 --- a/src/onebot/action/group/GetGroupMemberInfo.ts +++ b/src/onebot/action/group/GetGroupMemberInfo.ts @@ -26,20 +26,35 @@ class GetGroupMemberInfo extends OneBotAction { return uid; } - async _handle(payload: Payload) { - const isNocache = this.parseBoolean(payload.no_cache ?? true); - const uid = await this.getUid(payload.user_id); - const groupMember = this.core.apis.GroupApi.groupMemberCache.get(payload.group_id.toString())?.get(uid); - let [member, info] = await Promise.all([ + private async getGroupMemberInfo(payload: Payload, uid: string, isNocache: boolean) { + const groupMemberCache = this.core.apis.GroupApi.groupMemberCache.get(payload.group_id.toString()); + let groupMember = groupMemberCache?.get(uid); + + const [member, info] = await Promise.all([ this.core.apis.GroupApi.getGroupMemberEx(payload.group_id.toString(), uid, isNocache), this.core.apis.UserApi.getUserDetailInfo(uid), ]); - if (!member || !groupMember) throw new Error(`群(${payload.group_id})成员${payload.user_id}不存在`); - if (info) { - member = { ...groupMember, ...member, ...info }; - } else { + + if (!member) throw new Error(`群(${payload.group_id})成员${payload.user_id}不存在`); + + if (!groupMember && this.core.apis.GroupApi.groupMemberCacheEvent.get(payload.group_id.toString())) { + groupMember = (await this.core.apis.GroupApi.refreshGroupMemberCache(payload.group_id.toString(), true))?.get(uid); + } + + if (!groupMember) throw new Error(`群(${payload.group_id})成员${payload.user_id}不存在`); + + return info ? { ...groupMember, ...member, ...info } : member; + } + + async _handle(payload: Payload) { + const isNocache = this.parseBoolean(payload.no_cache ?? true); + const uid = await this.getUid(payload.user_id); + const member = await this.getGroupMemberInfo(payload, uid, isNocache); + + if (!member) { this.core.context.logger.logDebug(`获取群成员详细信息失败, 只能返回基础信息`); } + return OB11Construct.groupMember(payload.group_id.toString(), member); } } diff --git a/src/onebot/action/group/GetGroupMemberList.ts b/src/onebot/action/group/GetGroupMemberList.ts index 35500059..d7ec9657 100644 --- a/src/onebot/action/group/GetGroupMemberList.ts +++ b/src/onebot/action/group/GetGroupMemberList.ts @@ -3,6 +3,7 @@ import { OB11Construct } from '@/onebot/helper/data'; import { OneBotAction } from '@/onebot/action/OneBotAction'; import { ActionName } from '@/onebot/action/router'; import { Static, Type } from '@sinclair/typebox'; +import { GroupMember } from '@/core'; const SchemaData = Type.Object({ group_id: Type.Union([Type.Number(), Type.String()]), @@ -17,25 +18,32 @@ export class GetGroupMemberList extends OneBotAction async _handle(payload: Payload) { const groupIdStr = payload.group_id.toString(); - const noCache = payload.no_cache ? this.stringToBoolean(payload.no_cache) : false; + const noCache = this.parseBoolean(payload.no_cache ?? false); + const groupMembers = await this.getGroupMembers(groupIdStr, noCache); + const _groupMembers = await Promise.all( + Array.from(groupMembers.values()).map(item => + OB11Construct.groupMember(groupIdStr, item) + ) + ); + return Array.from(new Map(_groupMembers.map(member => [member.user_id, member])).values()); + } + + private parseBoolean(value: boolean | string): boolean { + return typeof value === 'string' ? value === 'true' : value; + } + + private async getGroupMembers(groupIdStr: string, noCache: boolean): Promise> { const memberCache = this.core.apis.GroupApi.groupMemberCache; let groupMembers = memberCache.get(groupIdStr); + if (noCache || !groupMembers) { - this.core.apis.GroupApi.refreshGroupMemberCache(groupIdStr).then().catch(); - //下次刷新 - groupMembers = memberCache.get(groupIdStr); + const data = this.core.apis.GroupApi.refreshGroupMemberCache(groupIdStr, true).then().catch(); + groupMembers = memberCache.get(groupIdStr) || (await data); if (!groupMembers) { throw new Error(`Failed to get group member list for group ${groupIdStr}`); } } - const memberPromises = Array.from(groupMembers.values()).map(item => - OB11Construct.groupMember(groupIdStr, item) - ); - const _groupMembers = await Promise.all(memberPromises); - const MemberMap = new Map(_groupMembers.map(member => [member.user_id, member])); - return Array.from(MemberMap.values()); + + return groupMembers; } - stringToBoolean(str: string | boolean): boolean { - return typeof str === 'boolean' ? str : str.toLowerCase() === "true"; - } -} +} \ No newline at end of file diff --git a/src/onebot/api/group.ts b/src/onebot/api/group.ts index 94464fd1..9f34c5a4 100644 --- a/src/onebot/api/group.ts +++ b/src/onebot/api/group.ts @@ -223,7 +223,7 @@ export class OneBotGroupApi { } else if (element.type === TipGroupElementType.KMEMBERADD) { // 自己的通知 协议推送为type->85 在这里实现为了避免邀请出现问题 if (element.memberUid == this.core.selfInfo.uid) { - this.core.apis.GroupApi.refreshGroupMemberCache(msg.peerUid).then().catch(); + await this.core.apis.GroupApi.refreshGroupMemberCache(msg.peerUid, false); return new OB11GroupIncreaseEvent( this.core, parseInt(msg.peerUid), diff --git a/src/onebot/api/msg.ts b/src/onebot/api/msg.ts index 1f2ca3ef..2e6b62c8 100644 --- a/src/onebot/api/msg.ts +++ b/src/onebot/api/msg.ts @@ -1022,7 +1022,7 @@ export class OneBotMsgApi { // 邀请需要解grayTipElement if (SysMessage.contentHead.type == 33 && SysMessage.body?.msgContent) { const groupChange = new NapProtoMsg(GroupChange).decode(SysMessage.body.msgContent); - this.core.apis.GroupApi.refreshGroupMemberCache(groupChange.groupUin.toString()).then().catch(); + await this.core.apis.GroupApi.refreshGroupMemberCache(groupChange.groupUin.toString(), false); let operatorUid = await this.waitGroupNotify( groupChange.groupUin.toString(), groupChange.memberUid, @@ -1052,7 +1052,7 @@ export class OneBotMsgApi { }, 5000); // 自己被踢了 5S后回收 } else { - this.core.apis.GroupApi.refreshGroupMemberCache(groupChange.groupUin.toString()).then().catch(); + await this.core.apis.GroupApi.refreshGroupMemberCache(groupChange.groupUin.toString(), false); } return new OB11GroupDecreaseEvent( this.core, @@ -1063,7 +1063,7 @@ export class OneBotMsgApi { ); } else if (SysMessage.contentHead.type == 44 && SysMessage.body?.msgContent) { const groupAmin = new NapProtoMsg(GroupAdmin).decode(SysMessage.body.msgContent); - this.core.apis.GroupApi.refreshGroupMemberCache(groupAmin.groupUin.toString()).then().catch(); + await this.core.apis.GroupApi.refreshGroupMemberCache(groupAmin.groupUin.toString(), false); let enabled = false; let uid = ''; if (groupAmin.body.extraEnable != null) {