diff --git a/client/guild.go b/client/guild.go index c555bf10..5f10138e 100644 --- a/client/guild.go +++ b/client/guild.go @@ -64,7 +64,8 @@ type ( Title string Nickname string LastSpeakTime int64 - Role int32 // 0 = member 1 = admin 2 = owner ? + Role uint64 + RoleName string } // GuildUserProfile 频道系统用户资料 @@ -122,6 +123,14 @@ type ( SlowModeText string } + FetchGuildMemberListWithRoleResult struct { + Members []*GuildMemberInfo + NextIndex uint32 + NextRoleId uint64 + NextQueryParam string + Finished bool + } + ChannelType int32 ) @@ -195,61 +204,66 @@ func (s *GuildService) GetUserProfile(tinyId uint64) (*GuildUserProfile, error) }, nil } -func (s *GuildService) GetGuildMembers(guildId uint64) (bots []*GuildMemberInfo, members []*GuildMemberInfo, admins []*GuildMemberInfo, err error) { - return s.fetchMemberListWithRole(guildId, 0, 2) -} - -func (s *GuildService) fetchMemberListWithRole(guildId uint64, startIndex, roleIdIndex uint32) (bots []*GuildMemberInfo, members []*GuildMemberInfo, admins []*GuildMemberInfo, err error) { - finished := false +// FetchGuildMemberListWithRole 获取频道成员列表 +// 第一次请求: startIndex = 0 , roleIdIndex = 2 param = "" +// 后续请求请根据上次请求的返回值进行设置 +func (s *GuildService) FetchGuildMemberListWithRole(guildId, channelId uint64, startIndex uint32, roleIdIndex uint64, param string) (*FetchGuildMemberListWithRoleResult, error) { + seq := s.c.nextSeq() u1 := uint32(1) - for !finished { - seq := s.c.nextSeq() - // todo: 按 channel 获取 member list - payload := s.c.packOIDBPackageDynamically(3931, 1, binary.DynamicProtoMessage{ - 1: guildId, // guild id - 2: uint32(3), - 3: uint32(0), - 4: binary.DynamicProtoMessage{ // unknown param, looks like flags - 1: u1, 2: u1, 3: u1, 4: u1, 5: u1, 6: u1, 7: u1, 8: u1, 20: u1, - }, - 6: startIndex, - 8: uint32(50), // count - 14: roleIdIndex, - }) - packet := packets.BuildUniPacket(s.c.Uin, seq, "OidbSvcTrpcTcp.0xf5b_1", 1, s.c.OutGoingPacketSessionId, []byte{}, s.c.sigInfo.d2Key, payload) - rsp, err := s.c.sendAndWaitDynamic(seq, packet) - if err != nil { - return nil, nil, nil, errors.Wrap(err, "send packet error") - } - body := new(channel.ChannelOidb0Xf5BRsp) - if err = s.c.unpackOIDBPackage(rsp, body); err != nil { - return nil, nil, nil, errors.Wrap(err, "decode packet error") - } - protoToMemberInfo := func(mem *channel.GuildMemberInfo) *GuildMemberInfo { - return &GuildMemberInfo{ + m := binary.DynamicProtoMessage{ + 1: guildId, // guild id + 2: uint32(3), + 3: uint32(0), + 4: binary.DynamicProtoMessage{ // unknown param, looks like flags + 1: u1, 2: u1, 3: u1, 4: u1, 5: u1, 6: u1, 7: u1, 8: u1, 20: u1, + }, + 6: startIndex, + 8: uint32(50), // count + 12: channelId, + } + if param != "" { + m[13] = param + } + m[14] = roleIdIndex + packet := packets.BuildUniPacket(s.c.Uin, seq, "OidbSvcTrpcTcp.0xf5b_1", 1, s.c.OutGoingPacketSessionId, []byte{}, s.c.sigInfo.d2Key, s.c.packOIDBPackageDynamically(3931, 1, m)) + rsp, err := s.c.sendAndWaitDynamic(seq, packet) + if err != nil { + return nil, errors.Wrap(err, "send packet error") + } + body := new(channel.ChannelOidb0Xf5BRsp) + if err = s.c.unpackOIDBPackage(rsp, body); err != nil { + return nil, errors.Wrap(err, "decode packet error") + } + var ret []*GuildMemberInfo + for _, memberWithRole := range body.MemberWithRoles { + for _, mem := range memberWithRole.Members { + ret = append(ret, &GuildMemberInfo{ TinyId: mem.GetTinyId(), Title: mem.GetTitle(), Nickname: mem.GetNickname(), LastSpeakTime: mem.GetLastSpeakTime(), - Role: mem.GetRole(), - } + Role: memberWithRole.GetRoleId(), + RoleName: memberWithRole.GetRoleName(), + }) } - for _, mem := range body.Bots { - bots = append(bots, protoToMemberInfo(mem)) - } - for _, mem := range body.Members { - members = append(members, protoToMemberInfo(mem)) - } - if body.AdminInfo != nil { - for _, mem := range body.AdminInfo.Admins { - admins = append(admins, protoToMemberInfo(mem)) - } - } - finished = body.NextIndex == nil || startIndex == body.GetNextIndex() // todo: 不知道什么情况, 某些群 nextIndex一直是一样的 - startIndex = body.GetNextIndex() - roleIdIndex = body.GetNextRoleIdIndex() } - return + for _, mem := range body.Members { + ret = append(ret, &GuildMemberInfo{ + TinyId: mem.GetTinyId(), + Title: mem.GetTitle(), + Nickname: mem.GetNickname(), + LastSpeakTime: mem.GetLastSpeakTime(), + Role: 1, + RoleName: "普通成员", + }) + } + return &FetchGuildMemberListWithRoleResult{ + Members: ret, + NextIndex: body.GetNextIndex(), + NextRoleId: body.GetNextRoleIdIndex(), + NextQueryParam: body.GetNextQueryParam(), + Finished: body.NextIndex == nil, + }, nil } func (s *GuildService) GetGuildMemberProfileInfo(guildId, tinyId uint64) (*GuildUserProfile, error) { diff --git a/client/pb/channel/unknown.pb.go b/client/pb/channel/unknown.pb.go index 30d7a8bf..7d5344d3 100644 --- a/client/pb/channel/unknown.pb.go +++ b/client/pb/channel/unknown.pb.go @@ -3,13 +3,16 @@ package channel +// see sub_37628C type ChannelOidb0Xf5BRsp struct { - GuildId *uint64 `protobuf:"varint,1,opt"` - Bots []*GuildMemberInfo `protobuf:"bytes,4,rep"` - Members []*GuildMemberInfo `protobuf:"bytes,5,rep"` - NextRoleIdIndex *uint32 `protobuf:"varint,8,opt"` - NextIndex *uint32 `protobuf:"varint,10,opt"` - AdminInfo *GuildAdminInfo `protobuf:"bytes,25,opt"` + GuildId *uint64 `protobuf:"varint,1,opt"` + Bots []*GuildMemberInfo `protobuf:"bytes,4,rep"` + Members []*GuildMemberInfo `protobuf:"bytes,5,rep"` + NextIndex *uint32 `protobuf:"varint,10,opt"` + Finished *uint32 `protobuf:"varint,9,opt"` + NextQueryParam *string `protobuf:"bytes,24,opt"` + MemberWithRoles []*GuildGroupMembersInfo `protobuf:"bytes,25,rep"` + NextRoleIdIndex *uint64 `protobuf:"varint,26,opt"` } func (x *ChannelOidb0Xf5BRsp) GetGuildId() uint64 { @@ -33,13 +36,6 @@ func (x *ChannelOidb0Xf5BRsp) GetMembers() []*GuildMemberInfo { return nil } -func (x *ChannelOidb0Xf5BRsp) GetNextRoleIdIndex() uint32 { - if x != nil && x.NextRoleIdIndex != nil { - return *x.NextRoleIdIndex - } - return 0 -} - func (x *ChannelOidb0Xf5BRsp) GetNextIndex() uint32 { if x != nil && x.NextIndex != nil { return *x.NextIndex @@ -47,13 +43,34 @@ func (x *ChannelOidb0Xf5BRsp) GetNextIndex() uint32 { return 0 } -func (x *ChannelOidb0Xf5BRsp) GetAdminInfo() *GuildAdminInfo { +func (x *ChannelOidb0Xf5BRsp) GetFinished() uint32 { + if x != nil && x.Finished != nil { + return *x.Finished + } + return 0 +} + +func (x *ChannelOidb0Xf5BRsp) GetNextQueryParam() string { + if x != nil && x.NextQueryParam != nil { + return *x.NextQueryParam + } + return "" +} + +func (x *ChannelOidb0Xf5BRsp) GetMemberWithRoles() []*GuildGroupMembersInfo { if x != nil { - return x.AdminInfo + return x.MemberWithRoles } return nil } +func (x *ChannelOidb0Xf5BRsp) GetNextRoleIdIndex() uint64 { + if x != nil && x.NextRoleIdIndex != nil { + return *x.NextRoleIdIndex + } + return 0 +} + type ChannelOidb0Xf88Rsp struct { Profile *GuildUserProfile `protobuf:"bytes,1,opt"` } @@ -207,17 +224,42 @@ func (x *ChannelListRsp) GetChannels() []*GuildChannelInfo { return nil } -type GuildAdminInfo struct { - Admins []*GuildMemberInfo `protobuf:"bytes,2,rep"` +type GuildGroupMembersInfo struct { + RoleId *uint64 `protobuf:"varint,1,opt"` + Members []*GuildMemberInfo `protobuf:"bytes,2,rep"` + RoleName *string `protobuf:"bytes,3,opt"` + Color *uint32 `protobuf:"varint,4,opt"` } -func (x *GuildAdminInfo) GetAdmins() []*GuildMemberInfo { +func (x *GuildGroupMembersInfo) GetRoleId() uint64 { + if x != nil && x.RoleId != nil { + return *x.RoleId + } + return 0 +} + +func (x *GuildGroupMembersInfo) GetMembers() []*GuildMemberInfo { if x != nil { - return x.Admins + return x.Members } return nil } +func (x *GuildGroupMembersInfo) GetRoleName() string { + if x != nil && x.RoleName != nil { + return *x.RoleName + } + return "" +} + +func (x *GuildGroupMembersInfo) GetColor() uint32 { + if x != nil && x.Color != nil { + return *x.Color + } + return 0 +} + +// see sub_374334 type GuildMemberInfo struct { Title *string `protobuf:"bytes,2,opt"` Nickname *string `protobuf:"bytes,3,opt"` diff --git a/client/pb/channel/unknown.proto b/client/pb/channel/unknown.proto index 79ef02cd..e0b855b5 100644 --- a/client/pb/channel/unknown.proto +++ b/client/pb/channel/unknown.proto @@ -5,13 +5,16 @@ package channel; option go_package = "pb/channel;channel"; +// see sub_37628C message ChannelOidb0xf5bRsp { optional uint64 guildId = 1; repeated GuildMemberInfo bots = 4; repeated GuildMemberInfo members = 5; - optional uint32 nextRoleIdIndex = 8; optional uint32 nextIndex = 10; - optional GuildAdminInfo adminInfo = 25; + optional uint32 finished = 9; + optional string nextQueryParam = 24; + repeated GuildGroupMembersInfo memberWithRoles = 25; + optional uint64 nextRoleIdIndex = 26; } message ChannelOidb0xf88Rsp { @@ -88,10 +91,14 @@ message ChannelListRsp { // 5: Category infos } -message GuildAdminInfo { - repeated GuildMemberInfo admins = 2; +message GuildGroupMembersInfo { + optional uint64 roleId = 1; + repeated GuildMemberInfo members = 2; + optional string roleName = 3; + optional uint32 color = 4; } +// see sub_374334 message GuildMemberInfo { optional string title = 2; optional string nickname = 3;