diff --git a/README.md b/README.md index 161ba721..6aab02d8 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ qq-android协议的golang实现 移植于Mirai - [x] 收到邀请进群通知 - [x] 收到其他用户进群请求 - [ ] 新好友 +- [x] 新好友请求 #### 主动操作 - [x] 发送群消息 @@ -48,7 +49,7 @@ qq-android协议的golang实现 移植于Mirai - [ ] 获取/刷新讨论组列表 - [ ] 处理加群请求 - [ ] 处理好友请求 -- [ ] 撤回消息 +- [ ] 撤回群消息 - [ ] 群公告设置 - [ ] 群设置 - [ ] 修改群成员Card diff --git a/client/builders.go b/client/builders.go index 82e077f7..c7d7ccee 100644 --- a/client/builders.go +++ b/client/builders.go @@ -503,3 +503,24 @@ func (c *QQClient) buildSystemMsgNewGroupPacket() (uint16, []byte) { 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() + req := &structmsg.ReqSystemMsgNew{ + MsgNum: 20, + Version: 1000, + Checktype: 2, + Flag: &structmsg.FlagInfo{ + FrdMsgDiscuss2ManyChat: 1, + FrdMsgGetBusiCard: 1, + FrdMsgNeedWaitingMsg: 1, + FrdMsgUint32NeedAllUnreadMsg: 1, + GrpMsgMaskInviteAutoJoin: 1, + }, + FriendMsgTypeFlag: 1, + } + payload, _ := proto.Marshal(req) + packet := packets.BuildUniPacket(c.Uin, seq, "ProfileService.Pb.ReqSystemMsgNew.Friend", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) + return seq, packet +} diff --git a/client/client.go b/client/client.go index caae27f9..63e65e9d 100644 --- a/client/client.go +++ b/client/client.go @@ -3,7 +3,6 @@ package client import ( "crypto/md5" "errors" - "fmt" "github.com/Mrs4s/MiraiGo/binary" "github.com/Mrs4s/MiraiGo/client/pb" "github.com/Mrs4s/MiraiGo/message" @@ -95,19 +94,20 @@ func NewClientMd5(uin int64, passwordMd5 [16]byte) *QQClient { RandomKey: make([]byte, 16), OutGoingPacketSessionId: []byte{0x02, 0xB0, 0x5B, 0x8B}, decoders: map[string]func(*QQClient, uint16, []byte) (interface{}, error){ - "wtlogin.login": decodeLoginResponse, - "StatSvc.register": decodeClientRegisterResponse, - "MessageSvc.PushNotify": decodeSvcNotify, - "OnlinePush.PbPushGroupMsg": decodeGroupMessagePacket, - "OnlinePush.ReqPush": decodeOnlinePushReqPacket, - "OnlinePush.PbPushTransMsg": decodeOnlinePushTransPacket, - "ConfigPushSvc.PushReq": decodePushReqPacket, - "MessageSvc.PbGetMsg": decodeMessageSvcPacket, - "friendlist.getFriendGroupList": decodeFriendGroupListResponse, - "friendlist.GetTroopListReqV2": decodeGroupListResponse, - "friendlist.GetTroopMemberListReq": decodeGroupMemberListResponse, - "ImgStore.GroupPicUp": decodeGroupImageStoreResponse, - "ProfileService.Pb.ReqSystemMsgNew.Group": decodeSystemMsgGroupPacket, + "wtlogin.login": decodeLoginResponse, + "StatSvc.register": decodeClientRegisterResponse, + "MessageSvc.PushNotify": decodeSvcNotify, + "OnlinePush.PbPushGroupMsg": decodeGroupMessagePacket, + "OnlinePush.ReqPush": decodeOnlinePushReqPacket, + "OnlinePush.PbPushTransMsg": decodeOnlinePushTransPacket, + "ConfigPushSvc.PushReq": decodePushReqPacket, + "MessageSvc.PbGetMsg": decodeMessageSvcPacket, + "friendlist.getFriendGroupList": decodeFriendGroupListResponse, + "friendlist.GetTroopListReqV2": decodeGroupListResponse, + "friendlist.GetTroopMemberListReq": decodeGroupMemberListResponse, + "ImgStore.GroupPicUp": decodeGroupImageStoreResponse, + "ProfileService.Pb.ReqSystemMsgNew.Group": decodeSystemMsgGroupPacket, + "ProfileService.Pb.ReqSystemMsgNew.Friend": decodeSystemMsgFriendPacket, }, handlers: map[uint16]func(interface{}, error){}, sigInfo: &loginSigInfo{}, @@ -464,7 +464,7 @@ func (c *QQClient) loop() { continue } } - fmt.Println(pkt.CommandName) + //fmt.Println(pkt.CommandName) go func() { decoder, ok := c.decoders[pkt.CommandName] if !ok { diff --git a/client/decoders.go b/client/decoders.go index f2b72779..faef8022 100644 --- a/client/decoders.go +++ b/client/decoders.go @@ -215,6 +215,9 @@ func decodeMessageSvcPacket(c *QQClient, _ uint16, payload []byte) (interface{}, } c.lastMessageSeq = message.Head.MsgSeq c.dispatchFriendMessage(c.parsePrivateMessage(message)) + case 187: + _, pkt := c.buildSystemMsgNewFriendPacket() + _ = c.send(pkt) } } } @@ -528,27 +531,49 @@ func decodeSystemMsgGroupPacket(c *QQClient, _ uint16, payload []byte) (interfac return nil, nil } st := rsp.Groupmsgs[0] - // 其他SubType不关心 - if st.Msg.SubType == 1 { - switch st.Msg.C2CInviteJoinGroupFlag { - case 0: //成员申请 - 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, - }) - case 1: // 被邀请 - c.dispatchGroupInvitedEvent(&GroupInvitedEvent{ - EventId: st.MsgSeq, - InvitorUin: st.Msg.ActionUin, - InvitorNick: st.Msg.ActionUinNick, - GroupCode: st.Msg.GroupCode, - GroupName: st.Msg.GroupName, - }) + if st.Msg != nil { + // 其他SubType不关心 + if st.Msg.SubType == 1 { + switch st.Msg.C2CInviteJoinGroupFlag { + case 0: //成员申请 + 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, + }) + case 1: // 被邀请 + c.dispatchGroupInvitedEvent(&GroupInvitedEvent{ + EventId: st.MsgSeq, + InvitorUin: st.Msg.ActionUin, + InvitorNick: st.Msg.ActionUinNick, + GroupCode: st.Msg.GroupCode, + GroupName: st.Msg.GroupName, + }) + } } } return nil, nil } + +func decodeSystemMsgFriendPacket(c *QQClient, _ uint16, payload []byte) (interface{}, error) { + rsp := structmsg.RspSystemMsgNew{} + if err := proto.Unmarshal(payload, &rsp); err != nil { + return nil, err + } + if len(rsp.Friendmsgs) == 0 { + return nil, nil + } + st := rsp.Friendmsgs[0] + if st.Msg != nil { + c.dispatchNewFriendRequest(&NewFriendRequest{ + RequestId: st.MsgSeq, + Message: st.Msg.MsgAdditional, + RequesterUin: st.ReqUin, + RequesterNick: st.Msg.ReqUinNick, + }) + } + return nil, nil +} diff --git a/client/entities.go b/client/entities.go index c0ae6e56..45ccb6f2 100644 --- a/client/entities.go +++ b/client/entities.go @@ -121,6 +121,13 @@ type ( GroupName string } + NewFriendRequest struct { + RequestId int64 + Message string + RequesterUin int64 + RequesterNick string + } + groupMemberListResponse struct { NextUin int64 list []*GroupMemberInfo diff --git a/client/events.go b/client/events.go index 0650b420..6f6f9856 100644 --- a/client/events.go +++ b/client/events.go @@ -18,6 +18,7 @@ type eventHandlers struct { permissionChangedHandlers []func(*QQClient, *MemberPermissionChangedEvent) groupInvitedHandlers []func(*QQClient, *GroupInvitedEvent) joinRequestHandlers []func(*QQClient, *UserJoinGroupRequest) + friendRequestHandlers []func(*QQClient, *NewFriendRequest) groupMessageReceiptHandlers sync.Map } @@ -77,6 +78,10 @@ func (c *QQClient) OnUserWantJoinGroup(f func(*QQClient, *UserJoinGroupRequest)) c.eventHandlers.joinRequestHandlers = append(c.eventHandlers.joinRequestHandlers, f) } +func (c *QQClient) OnNewFriendRequest(f func(*QQClient, *NewFriendRequest)) { + c.eventHandlers.friendRequestHandlers = append(c.eventHandlers.friendRequestHandlers, f) +} + func NewUinFilterPrivate(uin int64) func(*message.PrivateMessage) bool { return func(msg *message.PrivateMessage) bool { return msg.Sender.Uin == uin @@ -230,6 +235,17 @@ func (c *QQClient) dispatchJoinGroupRequest(r *UserJoinGroupRequest) { } } +func (c *QQClient) dispatchNewFriendRequest(r *NewFriendRequest) { + if r == nil { + return + } + for _, f := range c.eventHandlers.friendRequestHandlers { + cover(func() { + f(c, r) + }) + } +} + func cover(f func()) { defer func() { if pan := recover(); pan != nil {