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 aa67ba0d..cb222d11 100644 --- a/client/decoders.go +++ b/client/decoders.go @@ -7,7 +7,6 @@ import ( "github.com/Mrs4s/MiraiGo/client/pb/notify" "github.com/Mrs4s/MiraiGo/client/pb/pttcenter" "github.com/Mrs4s/MiraiGo/client/pb/qweb" - "log" "net" "strconv" "strings" @@ -304,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 @@ -934,55 +932,6 @@ func decodeOnlinePushTransPacket(c *QQClient, _ uint16, payload []byte) (interfa return nil, nil } -// ProfileService.Pb.ReqSystemMsgNew.Group -func decodeSystemMsgGroupPacket(c *QQClient, _ uint16, payload []byte) (interface{}, error) { - rsp := structmsg.RspSystemMsgNew{} - if err := proto.Unmarshal(payload, &rsp); err != nil { - return nil, err - } - if len(rsp.Groupmsgs) == 0 { - return nil, nil - } - st := rsp.Groupmsgs[0] - if st.Msg != nil { - if st.Msg.SubType == 1 { - // 处理被邀请入群 或 处理成员入群申请 - switch st.Msg.GroupMsgType { - case 1: // 成员申请 - c.dispatchJoinGroupRequest(&UserJoinGroupRequest{ - RequestId: st.MsgSeq, - Message: st.Msg.MsgAdditional, - RequesterUin: st.ReqUin, - RequesterNick: st.Msg.ReqUinNick, - GroupCode: st.Msg.GroupCode, - GroupName: st.Msg.GroupName, - client: c, - }) - case 2: // 被邀请 - c.dispatchGroupInvitedEvent(&GroupInvitedRequest{ - RequestId: st.MsgSeq, - InvitorUin: st.Msg.ActionUin, - InvitorNick: st.Msg.ActionUinNick, - GroupCode: st.Msg.GroupCode, - GroupName: st.Msg.GroupName, - client: c, - }) - default: - log.Println("unknown group msg:", st) - } - } 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) - } - } - return nil, nil -} - // ProfileService.Pb.ReqSystemMsgNew.Friend func decodeSystemMsgFriendPacket(c *QQClient, _ uint16, payload []byte) (interface{}, error) { rsp := structmsg.RspSystemMsgNew{} diff --git a/client/entities.go b/client/entities.go index 9687d744..172c6e83 100644 --- a/client/entities.go +++ b/client/entities.go @@ -151,27 +151,6 @@ type ( Message string } - GroupInvitedRequest struct { - RequestId int64 - InvitorUin int64 - InvitorNick string - GroupCode int64 - GroupName string - - client *QQClient - } - - UserJoinGroupRequest struct { - RequestId int64 - Message string - RequesterUin int64 - RequesterNick string - GroupCode int64 - GroupName string - - client *QQClient - } - NewFriendRequest struct { RequestId int64 Message string diff --git a/client/system_msg.go b/client/system_msg.go new file mode 100644 index 00000000..21801bf9 --- /dev/null +++ b/client/system_msg.go @@ -0,0 +1,172 @@ +package client + +import ( + "github.com/Mrs4s/MiraiGo/client/pb/structmsg" + "github.com/Mrs4s/MiraiGo/protocol/packets" + "google.golang.org/protobuf/proto" +) + +type ( + GroupSystemMessages struct { + InvitedRequests []*GroupInvitedRequest `json:"invited_requests"` + JoinRequests []*UserJoinGroupRequest `json:"join_requests"` + } + + GroupInvitedRequest struct { + 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 `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{} + if err := proto.Unmarshal(payload, &rsp); err != nil { + return nil, err + } + if len(rsp.Groupmsgs) == 0 { + return nil, nil + } + ret := &GroupSystemMessages{} + for _, st := range rsp.Groupmsgs { + if st.Msg == nil { + continue + } + switch st.Msg.SubType { + case 1, 2: // 处理被邀请入群 或 处理成员入群申请 + switch st.Msg.GroupMsgType { + case 1: // 成员申请 + ret.JoinRequests = append(ret.JoinRequests, &UserJoinGroupRequest{ + RequestId: st.MsgSeq, + Message: st.Msg.MsgAdditional, + RequesterUin: st.ReqUin, + 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: // 被邀请 + ret.InvitedRequests = append(ret.InvitedRequests, &GroupInvitedRequest{ + RequestId: st.MsgSeq, + InvitorUin: st.Msg.ActionUin, + InvitorNick: st.Msg.ActionUinNick, + GroupCode: st.Msg.GroupCode, + GroupName: st.Msg.GroupName, + Checked: st.Msg.SubType == 2, + Actor: st.Msg.ActorUin, + client: c, + }) + default: + c.Error("unknown group message type: %v", st.Msg.GroupMsgType) + } + case 3: // ? + case 5: // 自身状态变更(管理员/加群退群) + default: + c.Error("unknown group msg: %v", st.Msg.SubType) + } + } + return ret, nil +}