diff --git a/client/builders.go b/client/builders.go index 8001ec3c..608caeeb 100644 --- a/client/builders.go +++ b/client/builders.go @@ -769,38 +769,6 @@ func (c *QQClient) buildImageUploadPacket(data, updKey []byte, commandId int32, return } -// ProfileService.Pb.ReqSystemMsgNew.Group -func (c *QQClient) buildSystemMsgNewGroupPacket() (uint16, []byte) { - seq := c.nextSeq() - req := &structmsg.ReqSystemMsgNew{ - MsgNum: 100, - Version: 1000, - Checktype: 3, - Flag: &structmsg.FlagInfo{ - GrpMsgKickAdmin: 1, - GrpMsgHiddenGrp: 1, - GrpMsgWordingDown: 1, - GrpMsgGetOfficialAccount: 1, - GrpMsgGetPayInGroup: 1, - FrdMsgDiscuss2ManyChat: 1, - GrpMsgNotAllowJoinGrpInviteNotFrd: 1, - FrdMsgNeedWaitingMsg: 1, - FrdMsgUint32NeedAllUnreadMsg: 1, - GrpMsgNeedAutoAdminWording: 1, - GrpMsgGetTransferGroupMsgFlag: 1, - GrpMsgGetQuitPayGroupMsgFlag: 1, - GrpMsgSupportInviteAutoJoin: 1, - GrpMsgMaskInviteAutoJoin: 1, - GrpMsgGetDisbandedByAdmin: 1, - GrpMsgGetC2CInviteJoinGroup: 1, - }, - FriendMsgTypeFlag: 1, - } - payload, _ := proto.Marshal(req) - packet := packets.BuildUniPacket(c.Uin, seq, "ProfileService.Pb.ReqSystemMsgNew.Group", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) - return seq, packet -} - // ProfileService.Pb.ReqSystemMsgNew.Friend func (c *QQClient) buildSystemMsgNewFriendPacket() (uint16, []byte) { seq := c.nextSeq() diff --git a/client/client.go b/client/client.go index 5137eee6..edfcf76b 100644 --- a/client/client.go +++ b/client/client.go @@ -75,6 +75,7 @@ type QQClient struct { msgSvcCache *utils.Cache transCache *utils.Cache lastLostMsg string + groupSysMsgCache *GroupSystemMessages groupMsgBuilders sync.Map onlinePushCache *utils.Cache requestPacketRequestId int32 @@ -211,12 +212,7 @@ func (c *QQClient) Login() (*LoginResponse, error) { } l := rsp.(LoginResponse) if l.Success { - c.Online = true - c.lastLostMsg = "" - c.registerClient() - if !c.heartbeatEnabled { - c.startHeartbeat() - } + c.init() } return &l, nil } @@ -230,11 +226,7 @@ func (c *QQClient) SubmitCaptcha(result string, sign []byte) (*LoginResponse, er } l := rsp.(LoginResponse) if l.Success { - c.Online = true - c.registerClient() - if !c.heartbeatEnabled { - c.startHeartbeat() - } + c.init() } return &l, nil } @@ -246,15 +238,20 @@ func (c *QQClient) SubmitSMS(code string) (*LoginResponse, error) { } l := rsp.(LoginResponse) if l.Success { - c.Online = true - c.registerClient() - if !c.heartbeatEnabled { - c.startHeartbeat() - } + c.init() } return &l, nil } +func (c *QQClient) init() { + c.Online = true + c.registerClient() + c.groupSysMsgCache, _ = c.GetGroupSystemMessages() + if !c.heartbeatEnabled { + c.startHeartbeat() + } +} + func (c *QQClient) RequestSMS() bool { rsp, err := c.sendAndWait(c.buildSMSRequestPacket()) if err != nil { diff --git a/client/decoders.go b/client/decoders.go index f1a6fd04..cb222d11 100644 --- a/client/decoders.go +++ b/client/decoders.go @@ -303,8 +303,7 @@ func decodeMessageSvcPacket(c *QQClient, _ uint16, payload []byte) (interface{}, } groupJoinLock.Unlock() case 84, 87: - _, pkt := c.buildSystemMsgNewGroupPacket() - _ = c.send(pkt) + c.exceptAndDispatchGroupSysMsg() case 141: // 临时会话 if message.Head.C2CTmpMsgHead == nil { continue diff --git a/client/system_msg.go b/client/system_msg.go index 1ccfdde5..21801bf9 100644 --- a/client/system_msg.go +++ b/client/system_msg.go @@ -2,38 +2,123 @@ package client import ( "github.com/Mrs4s/MiraiGo/client/pb/structmsg" + "github.com/Mrs4s/MiraiGo/protocol/packets" "google.golang.org/protobuf/proto" - "log" ) type ( GroupSystemMessages struct { - InvitedRequests []*GroupInvitedRequest - JoinRequests []*UserJoinGroupRequest + InvitedRequests []*GroupInvitedRequest `json:"invited_requests"` + JoinRequests []*UserJoinGroupRequest `json:"join_requests"` } GroupInvitedRequest struct { - RequestId int64 - InvitorUin int64 - InvitorNick string - GroupCode int64 - GroupName string + RequestId int64 `json:"request_id"` + InvitorUin int64 `json:"invitor_uin"` + InvitorNick string `json:"invitor_nick"` + GroupCode int64 `json:"group_code"` + GroupName string `json:"group_name"` + + Checked bool `json:"checked"` + Actor int64 `json:"actor"` client *QQClient } UserJoinGroupRequest struct { - RequestId int64 - Message string - RequesterUin int64 - RequesterNick string - GroupCode int64 - GroupName string + RequestId int64 `json:"request_id"` + Message string `json:"message"` + RequesterUin int64 `json:"requester_uin"` + RequesterNick string `json:"requester_nick"` + GroupCode int64 `json:"group_code"` + GroupName string `json:"group_name"` + + Checked bool `json:"checked"` + Actor int64 `json:"actor"` client *QQClient } ) +func (c *QQClient) GetGroupSystemMessages() (*GroupSystemMessages, error) { + i, err := c.sendAndWait(c.buildSystemMsgNewGroupPacket()) + if err != nil { + return nil, err + } + return i.(*GroupSystemMessages), nil +} + +func (c *QQClient) exceptAndDispatchGroupSysMsg() { + if c.groupSysMsgCache == nil { + c.Error("warning: groupSysMsgCache is nil") + c.groupSysMsgCache, _ = c.GetGroupSystemMessages() + return + } + joinExists := func(req int64) bool { + for _, msg := range c.groupSysMsgCache.JoinRequests { + if req == msg.RequestId { + return true + } + } + return false + } + invExists := func(req int64) bool { + for _, msg := range c.groupSysMsgCache.InvitedRequests { + if req == msg.RequestId { + return true + } + } + return false + } + msgs, err := c.GetGroupSystemMessages() + if err != nil { + return + } + for _, msg := range msgs.JoinRequests { + if !joinExists(msg.RequestId) { + c.dispatchJoinGroupRequest(msg) + } + } + for _, msg := range msgs.InvitedRequests { + if !invExists(msg.RequestId) { + c.dispatchGroupInvitedEvent(msg) + } + } + c.groupSysMsgCache = msgs +} + +// ProfileService.Pb.ReqSystemMsgNew.Group +func (c *QQClient) buildSystemMsgNewGroupPacket() (uint16, []byte) { + seq := c.nextSeq() + req := &structmsg.ReqSystemMsgNew{ + MsgNum: 100, + Version: 1000, + Checktype: 3, + Flag: &structmsg.FlagInfo{ + GrpMsgKickAdmin: 1, + GrpMsgHiddenGrp: 1, + GrpMsgWordingDown: 1, + GrpMsgGetOfficialAccount: 1, + GrpMsgGetPayInGroup: 1, + FrdMsgDiscuss2ManyChat: 1, + GrpMsgNotAllowJoinGrpInviteNotFrd: 1, + FrdMsgNeedWaitingMsg: 1, + FrdMsgUint32NeedAllUnreadMsg: 1, + GrpMsgNeedAutoAdminWording: 1, + GrpMsgGetTransferGroupMsgFlag: 1, + GrpMsgGetQuitPayGroupMsgFlag: 1, + GrpMsgSupportInviteAutoJoin: 1, + GrpMsgMaskInviteAutoJoin: 1, + GrpMsgGetDisbandedByAdmin: 1, + GrpMsgGetC2CInviteJoinGroup: 1, + }, + FriendMsgTypeFlag: 1, + } + payload, _ := proto.Marshal(req) + packet := packets.BuildUniPacket(c.Uin, seq, "ProfileService.Pb.ReqSystemMsgNew.Group", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) + return seq, packet +} + // ProfileService.Pb.ReqSystemMsgNew.Group func decodeSystemMsgGroupPacket(c *QQClient, _ uint16, payload []byte) (interface{}, error) { rsp := structmsg.RspSystemMsgNew{} @@ -48,8 +133,8 @@ func decodeSystemMsgGroupPacket(c *QQClient, _ uint16, payload []byte) (interfac if st.Msg == nil { continue } - if st.Msg.SubType == 1 { - // 处理被邀请入群 或 处理成员入群申请 + switch st.Msg.SubType { + case 1, 2: // 处理被邀请入群 或 处理成员入群申请 switch st.Msg.GroupMsgType { case 1: // 成员申请 ret.JoinRequests = append(ret.JoinRequests, &UserJoinGroupRequest{ @@ -59,6 +144,8 @@ func decodeSystemMsgGroupPacket(c *QQClient, _ uint16, payload []byte) (interfac RequesterNick: st.Msg.ReqUinNick, GroupCode: st.Msg.GroupCode, GroupName: st.Msg.GroupName, + Checked: st.Msg.SubType == 2, + Actor: st.Msg.ActorUin, client: c, }) case 2: // 被邀请 @@ -68,19 +155,17 @@ func decodeSystemMsgGroupPacket(c *QQClient, _ uint16, payload []byte) (interfac InvitorNick: st.Msg.ActionUinNick, GroupCode: st.Msg.GroupCode, GroupName: st.Msg.GroupName, + Checked: st.Msg.SubType == 2, + Actor: st.Msg.ActorUin, client: c, }) default: - log.Println("unknown group msg:", st) + c.Error("unknown group message type: %v", st.Msg.GroupMsgType) } - } else if st.Msg.SubType == 2 { - // 被邀请入群, 自动同意, 不需处理 - } else if st.Msg.SubType == 3 { - // 已被其他管理员处理 - } else if st.Msg.SubType == 5 { - // 成员退群消息 - } else { - log.Println("unknown group msg:", st) + case 3: // ? + case 5: // 自身状态变更(管理员/加群退群) + default: + c.Error("unknown group msg: %v", st.Msg.SubType) } } return ret, nil