diff --git a/client/builders.go b/client/builders.go index ef836780..bd35c216 100644 --- a/client/builders.go +++ b/client/builders.go @@ -27,7 +27,7 @@ var ( syncConst2 = rand.Int63() ) -func (c *QQClient) buildLoginPacket() (uint16, []byte) { +func (c *QQClient) buildLoginRequest() *network.Request { seq := c.nextSeq() req := c.buildOicqRequestPacket(c.Uin, 0x0810, binary.NewWriterF(func(w *binary.Writer) { w.WriteUInt16(9) @@ -91,7 +91,7 @@ func (c *QQClient) buildLoginPacket() (uint16, []byte) { w.Write(tlv.T525(tlv.T536([]byte{0x01, 0x00}))) })) - req2 := network.Request{ + return &network.Request{ Type: network.RequestTypeLogin, EncryptType: network.EncryptTypeEmptyKey, SequenceID: int32(seq), @@ -99,10 +99,9 @@ func (c *QQClient) buildLoginPacket() (uint16, []byte) { CommandName: "wtlogin.login", Body: req, } - return seq, c.transport.PackPacket(&req2) } -func (c *QQClient) buildDeviceLockLoginPacket() (uint16, []byte) { +func (c *QQClient) buildDeviceLockLoginRequest() *network.Request { seq := c.nextSeq() req := c.buildOicqRequestPacket(c.Uin, 0x0810, binary.NewWriterF(func(w *binary.Writer) { w.WriteUInt16(20) @@ -113,7 +112,7 @@ func (c *QQClient) buildDeviceLockLoginPacket() (uint16, []byte) { w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap)) w.Write(tlv.T401(c.sig.G)) })) - req2 := network.Request{ + return &network.Request{ Type: network.RequestTypeLogin, EncryptType: network.EncryptTypeEmptyKey, SequenceID: int32(seq), @@ -121,10 +120,9 @@ func (c *QQClient) buildDeviceLockLoginPacket() (uint16, []byte) { CommandName: "wtlogin.login", Body: req, } - return seq, c.transport.PackPacket(&req2) } -func (c *QQClient) buildQRCodeFetchRequestPacket(size, margin, ecLevel uint32) (uint16, []byte) { +func (c *QQClient) buildQRCodeFetchRequest(size, margin, ecLevel uint32) *network.Request { watch := auth.AndroidWatch.Version() seq := c.nextSeq() req := c.buildOicqRequestPacket(0, 0x0812, binary.NewWriterF(func(w *binary.Writer) { @@ -147,7 +145,7 @@ func (c *QQClient) buildQRCodeFetchRequestPacket(size, margin, ecLevel uint32) ( })) })) - req2 := network.Request{ + return &network.Request{ Type: network.RequestTypeLogin, EncryptType: network.EncryptTypeEmptyKey, SequenceID: int32(seq), @@ -155,12 +153,9 @@ func (c *QQClient) buildQRCodeFetchRequestPacket(size, margin, ecLevel uint32) ( CommandName: "wtlogin.trans_emp", Body: req, } - return seq, c.transport.PackPacket(&req2) } -func (c *QQClient) buildQRCodeResultQueryRequestPacket(sig []byte) (uint16, []byte) { - version := c.transport.Version - c.transport.Version = auth.AndroidWatch.Version() +func (c *QQClient) buildQRCodeResultQueryRequest(sig []byte) *network.Request { seq := c.nextSeq() req := c.buildOicqRequestPacket(0, 0x0812, binary.NewWriterF(func(w *binary.Writer) { w.WriteHex(`0000620000001000000072000000`) // trans header @@ -178,7 +173,7 @@ func (c *QQClient) buildQRCodeResultQueryRequestPacket(sig []byte) (uint16, []by })) })) - req2 := network.Request{ + return &network.Request{ Type: network.RequestTypeLogin, EncryptType: network.EncryptTypeEmptyKey, SequenceID: int32(seq), @@ -186,12 +181,9 @@ func (c *QQClient) buildQRCodeResultQueryRequestPacket(sig []byte) (uint16, []by CommandName: "wtlogin.trans_emp", Body: req, } - payload := c.transport.PackPacket(&req2) - c.transport.Version = version - return seq, payload } -func (c *QQClient) buildQRCodeLoginPacket(t106, t16a, t318 []byte) (uint16, []byte) { +func (c *QQClient) buildQRCodeLoginRequest(t106, t16a, t318 []byte) *network.Request { seq := c.nextSeq() req := c.buildOicqRequestPacket(c.Uin, 0x0810, binary.NewWriterF(func(w *binary.Writer) { w.WriteUInt16(9) @@ -254,7 +246,7 @@ func (c *QQClient) buildQRCodeLoginPacket(t106, t16a, t318 []byte) (uint16, []by w.WriteBytesShort(t318) })) - req2 := network.Request{ + return &network.Request{ Type: network.RequestTypeLogin, EncryptType: network.EncryptTypeEmptyKey, SequenceID: int32(seq), @@ -262,10 +254,9 @@ func (c *QQClient) buildQRCodeLoginPacket(t106, t16a, t318 []byte) (uint16, []by CommandName: "wtlogin.login", Body: req, } - return seq, c.transport.PackPacket(&req2) } -func (c *QQClient) buildCaptchaPacket(result string, sign []byte) (uint16, []byte) { +func (c *QQClient) buildCaptchaRequest(result string, sign []byte) *network.Request { seq := c.nextSeq() req := c.buildOicqRequestPacket(c.Uin, 0x0810, binary.NewWriterF(func(w *binary.Writer) { w.WriteUInt16(2) // sub command @@ -277,7 +268,7 @@ func (c *QQClient) buildCaptchaPacket(result string, sign []byte) (uint16, []byt w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap)) })) - req2 := network.Request{ + return &network.Request{ Type: network.RequestTypeLogin, EncryptType: network.EncryptTypeEmptyKey, SequenceID: int32(seq), @@ -285,10 +276,9 @@ func (c *QQClient) buildCaptchaPacket(result string, sign []byte) (uint16, []byt CommandName: "wtlogin.login", Body: req, } - return seq, c.transport.PackPacket(&req2) } -func (c *QQClient) buildSMSRequestPacket() (uint16, []byte) { +func (c *QQClient) buildSMSRequest() *network.Request { seq := c.nextSeq() req := c.buildOicqRequestPacket(c.Uin, 0x0810, binary.NewWriterF(func(w *binary.Writer) { w.WriteUInt16(8) @@ -302,7 +292,7 @@ func (c *QQClient) buildSMSRequestPacket() (uint16, []byte) { w.Write(tlv.T197()) })) - req2 := network.Request{ + return &network.Request{ Type: network.RequestTypeLogin, EncryptType: network.EncryptTypeEmptyKey, SequenceID: int32(seq), @@ -310,10 +300,9 @@ func (c *QQClient) buildSMSRequestPacket() (uint16, []byte) { CommandName: "wtlogin.login", Body: req, } - return seq, c.transport.PackPacket(&req2) } -func (c *QQClient) buildSMSCodeSubmitPacket(code string) (uint16, []byte) { +func (c *QQClient) buildSMSCodeSubmitRequest(code string) *network.Request { seq := c.nextSeq() req := c.buildOicqRequestPacket(c.Uin, 0x0810, binary.NewWriterF(func(w *binary.Writer) { w.WriteUInt16(7) @@ -328,7 +317,7 @@ func (c *QQClient) buildSMSCodeSubmitPacket(code string) (uint16, []byte) { w.Write(tlv.T198()) })) - req2 := network.Request{ + return &network.Request{ Type: network.RequestTypeLogin, EncryptType: network.EncryptTypeEmptyKey, SequenceID: int32(seq), @@ -336,10 +325,9 @@ func (c *QQClient) buildSMSCodeSubmitPacket(code string) (uint16, []byte) { CommandName: "wtlogin.login", Body: req, } - return seq, c.transport.PackPacket(&req2) } -func (c *QQClient) buildTicketSubmitPacket(ticket string) (uint16, []byte) { +func (c *QQClient) buildTicketSubmitRequest(ticket string) *network.Request { seq := c.nextSeq() req := c.buildOicqRequestPacket(c.Uin, 0x0810, binary.NewWriterF(func(w *binary.Writer) { w.WriteUInt16(2) @@ -351,7 +339,7 @@ func (c *QQClient) buildTicketSubmitPacket(ticket string) (uint16, []byte) { w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap)) })) - req2 := network.Request{ + return &network.Request{ Type: network.RequestTypeLogin, EncryptType: network.EncryptTypeEmptyKey, SequenceID: int32(seq), @@ -359,10 +347,9 @@ func (c *QQClient) buildTicketSubmitPacket(ticket string) (uint16, []byte) { CommandName: "wtlogin.login", Body: req, } - return seq, c.transport.PackPacket(&req2) } -func (c *QQClient) buildRequestTgtgtNopicsigPacket() (uint16, []byte) { +func (c *QQClient) buildRequestTgtgtNopicsigRequest() *network.Request { seq := c.nextSeq() req := binary.NewWriterF(func(w *binary.Writer) { w.WriteUInt16(15) @@ -423,7 +410,7 @@ func (c *QQClient) buildRequestTgtgtNopicsigPacket() (uint16, []byte) { Body: req, } - nreq := network.Request{ + return &network.Request{ Type: network.RequestTypeSimple, EncryptType: network.EncryptTypeEmptyKey, Uin: c.Uin, @@ -431,10 +418,9 @@ func (c *QQClient) buildRequestTgtgtNopicsigPacket() (uint16, []byte) { CommandName: "wtlogin.exchange_emp", Body: c.oicq.Marshal(&m), } - return seq, c.transport.PackPacket(&nreq) } -func (c *QQClient) buildRequestChangeSigPacket(mainSigMap uint32) (uint16, []byte) { +func (c *QQClient) buildRequestChangeSigRequest(mainSigMap uint32) *network.Request { seq := c.nextSeq() req := c.buildOicqRequestPacket(c.Uin, 0x0810, binary.NewWriterF(func(w *binary.Writer) { w.WriteUInt16(11) @@ -477,7 +463,7 @@ func (c *QQClient) buildRequestChangeSigPacket(mainSigMap uint32) (uint16, []byt // w.Write(tlv.T202(c.deviceInfo.WifiBSSID, c.deviceInfo.WifiSSID)) })) - req2 := network.Request{ + return &network.Request{ Type: network.RequestTypeLogin, EncryptType: network.EncryptTypeEmptyKey, SequenceID: int32(seq), @@ -485,11 +471,10 @@ func (c *QQClient) buildRequestChangeSigPacket(mainSigMap uint32) (uint16, []byt CommandName: "wtlogin.exchange_emp", Body: req, } - return seq, c.transport.PackPacket(&req2) } // StatSvc.register -func (c *QQClient) buildClientRegisterPacket() (uint16, []byte) { +func (c *QQClient) buildClientRegisterPacket() *network.Request { seq := c.nextSeq() svc := &jce.SvcReqRegister{ ConnType: 0, @@ -532,7 +517,7 @@ func (c *QQClient) buildClientRegisterPacket() (uint16, []byte) { Status: make(map[string]string), } - req2 := network.Request{ + return &network.Request{ Type: network.RequestTypeLogin, EncryptType: network.EncryptTypeD2Key, SequenceID: int32(seq), @@ -540,10 +525,9 @@ func (c *QQClient) buildClientRegisterPacket() (uint16, []byte) { CommandName: "StatSvc.register", Body: pkt.ToBytes(), } - return seq, c.transport.PackPacket(&req2) } -func (c *QQClient) buildStatusSetPacket(status, extStatus int32) (uint16, []byte) { +func (c *QQClient) buildStatusSetPacket(status, extStatus int32) *network.Request { svc := &jce.SvcReqRegister{ ConnType: 0, Uin: c.Uin, @@ -576,11 +560,11 @@ func (c *QQClient) buildStatusSetPacket(status, extStatus int32) (uint16, []byte Context: make(map[string]string), Status: make(map[string]string), } - return c.uniPacket("StatSvc.SetStatusFromClient", pkt.ToBytes()) + return c.uniRequest("StatSvc.SetStatusFromClient", pkt.ToBytes()) } // ConfigPushSvc.PushResp -func (c *QQClient) buildConfPushRespPacket(t int32, pktSeq int64, jceBuf []byte) (uint16, []byte) { +func (c *QQClient) buildConfPushRespPacket(t int32, pktSeq int64, jceBuf []byte) *network.Request { req := jce.NewJceWriter() req.WriteInt32(t, 1) req.WriteInt64(pktSeq, 2) @@ -596,11 +580,11 @@ func (c *QQClient) buildConfPushRespPacket(t int32, pktSeq int64, jceBuf []byte) Context: make(map[string]string), Status: make(map[string]string), } - return c.uniPacket("ConfigPushSvc.PushResp", pkt.ToBytes()) + return c.uniRequest("ConfigPushSvc.PushResp", pkt.ToBytes()) } // friendlist.getFriendGroupList -func (c *QQClient) buildFriendGroupListRequestPacket(friendStartIndex, friendListCount, groupStartIndex, groupListCount int16) (uint16, []byte) { +func (c *QQClient) buildFriendGroupListRequest(friendStartIndex, friendListCount, groupStartIndex, groupListCount int16) *network.Request { d50, _ := proto.Marshal(&pb.D50ReqBody{ Appid: 1002, ReqMusicSwitch: 1, @@ -652,11 +636,11 @@ func (c *QQClient) buildFriendGroupListRequestPacket(friendStartIndex, friendLis Context: make(map[string]string), Status: make(map[string]string), } - return c.uniPacket("friendlist.getFriendGroupList", pkt.ToBytes()) + return c.uniRequest("friendlist.getFriendGroupList", pkt.ToBytes()) } // SummaryCard.ReqSummaryCard -func (c *QQClient) buildSummaryCardRequestPacket(target int64) (uint16, []byte) { +func (c *QQClient) buildSummaryCardRequest(target int64) *network.Request { seq := c.nextSeq() packBusinessBuf := func(t int32, buf []byte) []byte { return binary.NewWriterF(func(w *binary.Writer) { @@ -736,11 +720,11 @@ func (c *QQClient) buildSummaryCardRequestPacket(target int64) (uint16, []byte) Context: make(map[string]string), Status: make(map[string]string), } - return seq, c.uniPacketWithSeq(seq, "SummaryCard.ReqSummaryCard", pkt.ToBytes()) + return c.uniPacketWithSeq(seq, "SummaryCard.ReqSummaryCard", pkt.ToBytes()) } // friendlist.delFriend -func (c *QQClient) buildFriendDeletePacket(target int64) (uint16, []byte) { +func (c *QQClient) buildFriendDeletePacket(target int64) *network.Request { req := &jce.DelFriendReq{ Uin: c.Uin, DelUin: target, @@ -759,11 +743,11 @@ func (c *QQClient) buildFriendDeletePacket(target int64) (uint16, []byte) { Context: make(map[string]string), Status: make(map[string]string), } - return c.uniPacket("friendlist.delFriend", pkt.ToBytes()) + return c.uniRequest("friendlist.delFriend", pkt.ToBytes()) } // friendlist.GetTroopListReqV2 -func (c *QQClient) buildGroupListRequestPacket(vecCookie []byte) (uint16, []byte) { +func (c *QQClient) buildGroupListRequest(vecCookie []byte) *network.Request { req := &jce.TroopListRequest{ Uin: c.Uin, GetMSFMsgFlag: 1, @@ -788,11 +772,11 @@ func (c *QQClient) buildGroupListRequestPacket(vecCookie []byte) (uint16, []byte Context: make(map[string]string), Status: make(map[string]string), } - return c.uniPacket("friendlist.GetTroopListReqV2", pkt.ToBytes()) + return c.uniRequest("friendlist.GetTroopListReqV2", pkt.ToBytes()) } // friendlist.GetTroopMemberListReq -func (c *QQClient) buildGroupMemberListRequestPacket(groupUin, groupCode, nextUin int64) (uint16, []byte) { +func (c *QQClient) buildGroupMemberListRequest(groupUin, groupCode, nextUin int64) *network.Request { req := &jce.TroopMemberListRequest{ Uin: c.Uin, GroupCode: groupCode, @@ -814,11 +798,11 @@ func (c *QQClient) buildGroupMemberListRequestPacket(groupUin, groupCode, nextUi Context: make(map[string]string), Status: make(map[string]string), } - return c.uniPacket("friendlist.GetTroopMemberListReq", pkt.ToBytes()) + return c.uniRequest("friendlist.GetTroopMemberListReq", pkt.ToBytes()) } // group_member_card.get_group_member_card_info -func (c *QQClient) buildGroupMemberInfoRequestPacket(groupCode, uin int64) (uint16, []byte) { +func (c *QQClient) buildGroupMemberInfoRequest(groupCode, uin int64) *network.Request { req := &pb.GroupMemberReqBody{ GroupCode: groupCode, Uin: uin, @@ -827,7 +811,7 @@ func (c *QQClient) buildGroupMemberInfoRequestPacket(groupCode, uin int64) (uint RichCardNameVer: 1, } payload, _ := proto.Marshal(req) - return c.uniPacket("group_member_card.get_group_member_card_info", payload) + return c.uniRequest("group_member_card.get_group_member_card_info", payload) } // MessageSvc.PbGetMsg @@ -856,14 +840,15 @@ func (c *QQClient) buildGetMessageRequestPacket(flag msg.SyncFlag, msgTime int64 ServerBuf: EmptyBytes, } payload, _ := proto.Marshal(req) - return c.uniPacket("MessageSvc.PbGetMsg", payload) + req2 := c.uniRequest("MessageSvc.PbGetMsg", payload) + return uint16(req2.SequenceID), c.transport.PackPacket(req2) } // MessageSvc.PbDeleteMsg -func (c *QQClient) buildDeleteMessageRequestPacket(msg []*pb.MessageItem) (uint16, []byte) { +func (c *QQClient) buildDeleteMessageRequestPacket(msg []*pb.MessageItem) *network.Request { req := &pb.DeleteMessageRequest{Items: msg} payload, _ := proto.Marshal(req) - return c.uniPacket("MessageSvc.PbDeleteMsg", payload) + return c.uniRequest("MessageSvc.PbDeleteMsg", payload) } // OnlinePush.RespPush @@ -890,11 +875,11 @@ func (c *QQClient) buildDeleteOnlinePushPacket(uin int64, svrip int32, pushToken Context: make(map[string]string), Status: make(map[string]string), } - return c.uniPacketWithSeq(seq, "OnlinePush.RespPush", pkt.ToBytes()) + return c.transport.PackPacket(c.uniPacketWithSeq(seq, "OnlinePush.RespPush", pkt.ToBytes())) } // LongConn.OffPicUp -func (c *QQClient) buildOffPicUpPacket(target int64, md5 []byte, size int32) (uint16, []byte) { +func (c *QQClient) buildOffPicUpRequest(target int64, md5 []byte, size int32) *network.Request { req := &cmd0x352.ReqBody{ Subcmd: proto.Uint32(1), TryupImgReq: []*cmd0x352.D352TryUpImgReq{ @@ -917,11 +902,11 @@ func (c *QQClient) buildOffPicUpPacket(target int64, md5 []byte, size int32) (ui }, } payload, _ := proto.Marshal(req) - return c.uniPacket("LongConn.OffPicUp", payload) + return c.uniRequest("LongConn.OffPicUp", payload) } // ProfileService.Pb.ReqSystemMsgNew.Friend -func (c *QQClient) buildSystemMsgNewFriendPacket() (uint16, []byte) { +func (c *QQClient) buildSystemMsgNewFriendRequest() *network.Request { req := &structmsg.ReqSystemMsgNew{ MsgNum: 20, Version: 1000, @@ -936,11 +921,11 @@ func (c *QQClient) buildSystemMsgNewFriendPacket() (uint16, []byte) { FriendMsgTypeFlag: 1, } payload, _ := proto.Marshal(req) - return c.uniPacket("ProfileService.Pb.ReqSystemMsgNew.Friend", payload) + return c.uniRequest("ProfileService.Pb.ReqSystemMsgNew.Friend", payload) } // friendlist.ModifyGroupCardReq -func (c *QQClient) buildEditGroupTagPacket(groupCode, memberUin int64, newTag string) (uint16, []byte) { +func (c *QQClient) buildEditGroupTagPacket(groupCode, memberUin int64, newTag string) *network.Request { req := &jce.ModifyGroupCardRequest{ GroupCode: groupCode, UinInfo: []jce.IJceStruct{ @@ -961,11 +946,11 @@ func (c *QQClient) buildEditGroupTagPacket(groupCode, memberUin int64, newTag st Context: map[string]string{}, Status: map[string]string{}, } - return c.uniPacket("friendlist.ModifyGroupCardReq", pkt.ToBytes()) + return c.uniRequest("friendlist.ModifyGroupCardReq", pkt.ToBytes()) } // OidbSvc.0x8fc_2 -func (c *QQClient) buildEditSpecialTitlePacket(groupCode, memberUin int64, newTitle string) (uint16, []byte) { +func (c *QQClient) buildEditSpecialTitlePacket(groupCode, memberUin int64, newTitle string) *network.Request { body := &oidb.D8FCReqBody{ GroupCode: &groupCode, MemLevelInfo: []*oidb.D8FCMemberInfo{ @@ -979,18 +964,18 @@ func (c *QQClient) buildEditSpecialTitlePacket(groupCode, memberUin int64, newTi } b, _ := proto.Marshal(body) payload := c.packOIDBPackage(2300, 2, b) - return c.uniPacket("OidbSvc.0x8fc_2", payload) + return c.uniRequest("OidbSvc.0x8fc_2", payload) } // OidbSvc.0x89a_0 -func (c *QQClient) buildGroupOperationPacket(body *oidb.D89AReqBody) (uint16, []byte) { +func (c *QQClient) buildGroupOperationPacket(body *oidb.D89AReqBody) *network.Request { b, _ := proto.Marshal(body) payload := c.packOIDBPackage(2202, 0, b) - return c.uniPacket("OidbSvc.0x89a_0", payload) + return c.uniRequest("OidbSvc.0x89a_0", payload) } // OidbSvc.0x89a_0 -func (c *QQClient) buildGroupNameUpdatePacket(groupCode int64, newName string) (uint16, []byte) { +func (c *QQClient) buildGroupNameUpdateRequest(groupCode int64, newName string) *network.Request { body := &oidb.D89AReqBody{ GroupCode: groupCode, StGroupInfo: &oidb.D89AGroupinfo{ @@ -1000,7 +985,7 @@ func (c *QQClient) buildGroupNameUpdatePacket(groupCode int64, newName string) ( return c.buildGroupOperationPacket(body) } -func (c *QQClient) buildGroupMemoUpdatePacket(groupCode int64, newMemo string) (uint16, []byte) { +func (c *QQClient) buildGroupMemoUpdatePacket(groupCode int64, newMemo string) *network.Request { body := &oidb.D89AReqBody{ GroupCode: groupCode, StGroupInfo: &oidb.D89AGroupinfo{ @@ -1011,7 +996,7 @@ func (c *QQClient) buildGroupMemoUpdatePacket(groupCode int64, newMemo string) ( } // OidbSvc.0x89a_0 -func (c *QQClient) buildGroupMuteAllPacket(groupCode int64, mute bool) (uint16, []byte) { +func (c *QQClient) buildGroupMuteAllPacket(groupCode int64, mute bool) *network.Request { shutUpTime := int32(0) if mute { shutUpTime = 268435455 @@ -1026,7 +1011,7 @@ func (c *QQClient) buildGroupMuteAllPacket(groupCode int64, mute bool) (uint16, } // OidbSvc.0x8a0_0 -func (c *QQClient) buildGroupKickPacket(groupCode, memberUin int64, kickMsg string, block bool) (uint16, []byte) { +func (c *QQClient) buildGroupKickPacket(groupCode, memberUin int64, kickMsg string, block bool) *network.Request { flagBlock := 0 if block { flagBlock = 1 @@ -1044,11 +1029,11 @@ func (c *QQClient) buildGroupKickPacket(groupCode, memberUin int64, kickMsg stri } b, _ := proto.Marshal(body) payload := c.packOIDBPackage(2208, 0, b) - return c.uniPacket("OidbSvc.0x8a0_0", payload) + return c.uniRequest("OidbSvc.0x8a0_0", payload) } // OidbSvc.0x570_8 -func (c *QQClient) buildGroupMutePacket(groupCode, memberUin int64, time uint32) (uint16, []byte) { +func (c *QQClient) buildGroupMutePacket(groupCode, memberUin int64, time uint32) *network.Request { b, cl := binary.OpenWriterF(func(w *binary.Writer) { w.WriteUInt32(uint32(groupCode)) w.WriteByte(32) @@ -1058,33 +1043,33 @@ func (c *QQClient) buildGroupMutePacket(groupCode, memberUin int64, time uint32) }) payload := c.packOIDBPackage(1392, 8, b) cl() - return c.uniPacket("OidbSvc.0x570_8", payload) + return c.uniRequest("OidbSvc.0x570_8", payload) } // OidbSvc.0xed3 -func (c *QQClient) buildGroupPokePacket(groupCode, target int64) (uint16, []byte) { +func (c *QQClient) buildGroupPokeRequest(groupCode, target int64) *network.Request { body := &oidb.DED3ReqBody{ ToUin: target, GroupCode: groupCode, } b, _ := proto.Marshal(body) payload := c.packOIDBPackage(3795, 1, b) - return c.uniPacket("OidbSvc.0xed3", payload) + return c.uniRequest("OidbSvc.0xed3", payload) } // OidbSvc.0xed3 -func (c *QQClient) buildFriendPokePacket(target int64) (uint16, []byte) { +func (c *QQClient) buildFriendPokeRequest(target int64) *network.Request { body := &oidb.DED3ReqBody{ ToUin: target, AioUin: target, } b, _ := proto.Marshal(body) payload := c.packOIDBPackage(3795, 1, b) - return c.uniPacket("OidbSvc.0xed3", payload) + return c.uniRequest("OidbSvc.0xed3", payload) } // OidbSvc.0x55c_1 -func (c *QQClient) buildGroupAdminSetPacket(groupCode, member int64, flag bool) (uint16, []byte) { +func (c *QQClient) buildGroupAdminSetPacket(groupCode, member int64, flag bool) *network.Request { b, cl := binary.OpenWriterF(func(w *binary.Writer) { w.WriteUInt32(uint32(groupCode)) w.WriteUInt32(uint32(member)) @@ -1092,11 +1077,11 @@ func (c *QQClient) buildGroupAdminSetPacket(groupCode, member int64, flag bool) }) payload := c.packOIDBPackage(1372, 1, b) cl() - return c.uniPacket("OidbSvc.0x55c_1", payload) + return c.uniRequest("OidbSvc.0x55c_1", payload) } // ProfileService.GroupMngReq -func (c *QQClient) buildQuitGroupPacket(groupCode int64) (uint16, []byte) { +func (c *QQClient) buildQuitGroupPacket(groupCode int64) *network.Request { jw := jce.NewJceWriter() jw.WriteInt32(2, 0) jw.WriteInt64(c.Uin, 1) @@ -1116,12 +1101,12 @@ func (c *QQClient) buildQuitGroupPacket(groupCode int64) (uint16, []byte) { Context: map[string]string{}, Status: map[string]string{}, } - return c.uniPacket("ProfileService.GroupMngReq", pkt.ToBytes()) + return c.uniRequest("ProfileService.GroupMngReq", pkt.ToBytes()) } /* this function is unused // LightAppSvc.mini_app_info.GetAppInfoById -func (c *QQClient) buildAppInfoRequestPacket(id string) (uint16, []byte) { +func (c *QQClient) buildAppInfoRequestPacket(id string) *network.Request { seq := c.nextSeq() req := &qweb.GetAppInfoByIdReq{ AppId: id, @@ -1141,11 +1126,11 @@ func (c *QQClient) buildAppInfoRequestPacket(id string) (uint16, []byte) { } */ -func (c *QQClient) buildWordSegmentationPacket(data []byte) (uint16, []byte) { +func (c *QQClient) buildWordSegmentationPacket(data []byte) *network.Request { payload := c.packOIDBPackageProto(3449, 1, &oidb.D79ReqBody{ Uin: uint64(c.Uin), Content: data, Qua: []byte("and_537065262_8.4.5"), }) - return c.uniPacket("OidbSvc.0xd79", payload) + return c.uniRequest("OidbSvc.0xd79", payload) } diff --git a/client/c2c_processor.go b/client/c2c_processor.go index 7ed94072..3c9e85f6 100644 --- a/client/c2c_processor.go +++ b/client/c2c_processor.go @@ -68,7 +68,7 @@ func (c *QQClient) c2cMessageSyncProcessor(rsp *msg.GetMessageResponse, resp *ne } } if delItems != nil { - _, _ = c.sendAndWait(c.buildDeleteMessageRequestPacket(delItems)) + _, _ = c.call(c.buildDeleteMessageRequestPacket(delItems)) } if rsp.GetSyncFlag() != msg.SyncFlag_STOP { c.Debug("continue sync with flag: %v", rsp.SyncFlag) @@ -227,8 +227,7 @@ func troopAddMemberBroadcastDecoder(c *QQClient, pMsg *msg.Message, resp *networ } func systemMessageDecoder(c *QQClient, _ *msg.Message, _ *network.Response) { - _, pkt := c.buildSystemMsgNewFriendPacket() - _ = c.sendPacket(pkt) + _, _ = c.call(c.buildSystemMsgNewFriendRequest()) } func troopSystemMessageDecoder(c *QQClient, pMsg *msg.Message, info *network.Response) { @@ -257,7 +256,8 @@ func msgType0x211Decoder(c *QQClient, pMsg *msg.Message, info *network.Response) return } if sub4.NotOnlineFile != nil && sub4.NotOnlineFile.GetSubcmd() == 1 { // subcmd: 1 -> sendPacket, 2-> recv - rsp, err := c.sendAndWait(c.buildOfflineFileDownloadRequestPacket(sub4.NotOnlineFile.FileUuid)) // offline_file.go + rsp, err := c.callAndDecode(c.buildOfflineFileDownloadRequestPacket(sub4.NotOnlineFile.FileUuid), + decodeOfflineFileDownloadResponse) // offline_file.go if err != nil { return } diff --git a/client/client.go b/client/client.go index 8ed37b2e..aa8c49bf 100644 --- a/client/client.go +++ b/client/client.go @@ -50,9 +50,12 @@ type QQClient struct { SequenceId atomic.Int32 SessionId []byte RandomKey []byte - TCP *network.TCPListener // todo: combine other protocol state into one struct + TCP *network.TCPListener ConnectTime time.Time + // todo: combine net conn, transport, pending into one struct + pendingMu sync.Mutex + pending map[uint16]*network.Call transport *network.Transport oicq *oicq.Codec @@ -117,30 +120,14 @@ func (h *handlerInfo) getParams() network.RequestParams { } var decoders = map[string]func(*QQClient, *network.Response) (interface{}, error){ - "wtlogin.login": decodeLoginResponse, - "wtlogin.exchange_emp": decodeExchangeEmpResponse, - "wtlogin.trans_emp": decodeTransEmpResponse, - "StatSvc.register": decodeClientRegisterResponse, - "StatSvc.ReqMSFOffline": decodeMSFOfflinePacket, - "MessageSvc.PushNotify": decodeSvcNotify, - "OnlinePush.ReqPush": decodeOnlinePushReqPacket, - "OnlinePush.PbPushTransMsg": decodeOnlinePushTransPacket, - "OnlinePush.SidTicketExpired": decodeSidExpiredPacket, - "ConfigPushSvc.PushReq": decodePushReqPacket, - "MessageSvc.PbGetMsg": decodeMessageSvcPacket, - "MessageSvc.PushForceOffline": decodeForceOfflinePacket, - "PbMessageSvc.PbMsgWithDraw": decodeMsgWithDrawResponse, - "friendlist.getFriendGroupList": decodeFriendGroupListResponse, - "friendlist.delFriend": decodeFriendDeleteResponse, - "friendlist.GetTroopListReqV2": decodeGroupListResponse, - "friendlist.GetTroopMemberListReq": decodeGroupMemberListResponse, - "group_member_card.get_group_member_card_info": decodeGroupMemberInfoResponse, - "LongConn.OffPicUp": decodeOffPicUpResponse, - "ProfileService.Pb.ReqSystemMsgNew.Group": decodeSystemMsgGroupPacket, - "ProfileService.Pb.ReqSystemMsgNew.Friend": decodeSystemMsgFriendPacket, - "OidbSvc.0xd79": decodeWordSegmentation, - "OidbSvc.0x990": decodeTranslateResponse, - "SummaryCard.ReqSummaryCard": decodeSummaryCardResponse, + "StatSvc.ReqMSFOffline": decodeMSFOfflinePacket, + "MessageSvc.PushNotify": decodeSvcNotify, + "OnlinePush.ReqPush": decodeOnlinePushReqPacket, + "OnlinePush.PbPushTransMsg": decodeOnlinePushTransPacket, + "OnlinePush.SidTicketExpired": decodeSidExpiredPacket, + "ConfigPushSvc.PushReq": decodePushReqPacket, + "MessageSvc.PbGetMsg": decodeMessageSvcPacket, + "MessageSvc.PushForceOffline": decodeForceOfflinePacket, } func init() { @@ -173,6 +160,7 @@ func NewClientMd5(uin int64, passwordMd5 [16]byte) *QQClient { alive: true, highwaySession: new(highway.Session), + pending: make(map[uint16]*network.Call), version: new(auth.AppVersion), deviceInfo: new(auth.Device), } @@ -268,7 +256,7 @@ func (c *QQClient) Login() (*LoginResponse, error) { if err != nil { return nil, err } - rsp, err := c.sendAndWait(c.buildLoginPacket()) + rsp, err := c.callAndDecode(c.buildLoginRequest(), decodeLoginResponse) if err != nil { c.Disconnect() return nil, err @@ -302,7 +290,7 @@ func (c *QQClient) TokenLogin(token []byte) error { // SystemDeviceInfo.TgtgtKey = r.ReadBytesShort() c.deviceInfo.TgtgtKey = r.ReadBytesShort() } - _, err = c.sendAndWait(c.buildRequestChangeSigPacket(c.version.MainSigMap)) + _, err = c.callAndDecode(c.buildRequestChangeSigRequest(c.version.MainSigMap), decodeExchangeEmpResponse) if err != nil { return err } @@ -321,7 +309,9 @@ func (c *QQClient) FetchQRCodeCustomSize(size, margin, ecLevel uint32) (*QRCodeL if err != nil { return nil, err } - i, err := c.sendAndWait(c.buildQRCodeFetchRequestPacket(size, margin, ecLevel)) + c.transport.Version = auth.AndroidWatch.Version() + i, err := c.callAndDecode(c.buildQRCodeFetchRequest(size, margin, ecLevel), decodeTransEmpResponse) + c.transport.Version = c.version if err != nil { return nil, errors.Wrap(err, "fetch qrcode error") } @@ -329,7 +319,9 @@ func (c *QQClient) FetchQRCodeCustomSize(size, margin, ecLevel uint32) (*QRCodeL } func (c *QQClient) QueryQRCodeStatus(sig []byte) (*QRCodeLoginResponse, error) { - i, err := c.sendAndWait(c.buildQRCodeResultQueryRequestPacket(sig)) + c.transport.Version = auth.AndroidWatch.Version() + i, err := c.callAndDecode(c.buildQRCodeResultQueryRequest(sig), decodeTransEmpResponse) + c.transport.Version = c.version if err != nil { return nil, errors.Wrap(err, "query result error") } @@ -337,7 +329,7 @@ func (c *QQClient) QueryQRCodeStatus(sig []byte) (*QRCodeLoginResponse, error) { } func (c *QQClient) QRCodeLogin(info *QRCodeLoginInfo) (*LoginResponse, error) { - i, err := c.sendAndWait(c.buildQRCodeLoginPacket(info.tmpPwd, info.tmpNoPicSig, info.tgtQR)) + i, err := c.callAndDecode(c.buildQRCodeLoginRequest(info.tmpPwd, info.tmpNoPicSig, info.tgtQR), decodeLoginResponse) if err != nil { return nil, errors.Wrap(err, "qrcode login error") } @@ -350,8 +342,8 @@ func (c *QQClient) QRCodeLogin(info *QRCodeLoginInfo) (*LoginResponse, error) { // SubmitCaptcha send captcha to server func (c *QQClient) SubmitCaptcha(result string, sign []byte) (*LoginResponse, error) { - seq, packet := c.buildCaptchaPacket(result, sign) - rsp, err := c.sendAndWait(seq, packet) + req := c.buildCaptchaRequest(result, sign) + rsp, err := c.callAndDecode(req, decodeLoginResponse) if err != nil { c.Disconnect() return nil, err @@ -364,8 +356,8 @@ func (c *QQClient) SubmitCaptcha(result string, sign []byte) (*LoginResponse, er } func (c *QQClient) SubmitTicket(ticket string) (*LoginResponse, error) { - seq, packet := c.buildTicketSubmitPacket(ticket) - rsp, err := c.sendAndWait(seq, packet) + req := c.buildTicketSubmitRequest(ticket) + rsp, err := c.callAndDecode(req, decodeLoginResponse) if err != nil { c.Disconnect() return nil, err @@ -378,7 +370,7 @@ func (c *QQClient) SubmitTicket(ticket string) (*LoginResponse, error) { } func (c *QQClient) SubmitSMS(code string) (*LoginResponse, error) { - rsp, err := c.sendAndWait(c.buildSMSCodeSubmitPacket(code)) + rsp, err := c.callAndDecode(c.buildSMSCodeSubmitRequest(code), decodeLoginResponse) if err != nil { c.Disconnect() return nil, err @@ -391,7 +383,7 @@ func (c *QQClient) SubmitSMS(code string) (*LoginResponse, error) { } func (c *QQClient) RequestSMS() bool { - rsp, err := c.sendAndWait(c.buildSMSRequestPacket()) + rsp, err := c.callAndDecode(c.buildSMSRequest(), decodeLoginResponse) if err != nil { c.Error("request sms error: %v", err) return false @@ -431,8 +423,8 @@ func (c *QQClient) init(tokenLogin bool) error { } _ = c.RefreshStatus() if c.version.Protocol == auth.QiDian { - _, _ = c.sendAndWait(c.buildLoginExtraPacket()) // 小登录 - _, _ = c.sendAndWait(c.buildConnKeyRequestPacket()) // big data key 如果等待 config push 的话时间来不及 + _, _ = c.callAndDecode(c.buildLoginExtraPacket(), decodeLoginExtraResponse) // 小登录 + _, _ = c.callAndDecode(c.buildConnKeyRequestPacket(), decodeConnKeyResponse) // big data key 如果等待 config push 的话时间来不及 } seq, pkt := c.buildGetMessageRequestPacket(msg.SyncFlag_START, time.Now().Unix()) _, _ = c.sendAndWaitParams(seq, pkt, network.RequestParams{"used_reg_proxy": true, "init": true}) @@ -457,14 +449,14 @@ func (c *QQClient) GenToken() []byte { func (c *QQClient) SetOnlineStatus(s UserOnlineStatus) { if s < 1000 { - _, _ = c.sendAndWait(c.buildStatusSetPacket(int32(s), 0)) + _, _ = c.call(c.buildStatusSetPacket(int32(s), 0)) return } - _, _ = c.sendAndWait(c.buildStatusSetPacket(11, int32(s))) + _, _ = c.call(c.buildStatusSetPacket(11, int32(s))) } func (c *QQClient) GetWordSegmentation(text string) ([]string, error) { - rsp, err := c.sendAndWait(c.buildWordSegmentationPacket([]byte(text))) + rsp, err := c.callAndDecode(c.buildWordSegmentationPacket([]byte(text)), decodeWordSegmentation) if err != nil { return nil, err } @@ -479,7 +471,7 @@ func (c *QQClient) GetWordSegmentation(text string) ([]string, error) { } func (c *QQClient) GetSummaryInfo(target int64) (*SummaryCardInfo, error) { - rsp, err := c.sendAndWait(c.buildSummaryCardRequestPacket(target)) + rsp, err := c.callAndDecode(c.buildSummaryCardRequest(target), decodeSummaryCardResponse) if err != nil { return nil, err } @@ -510,7 +502,8 @@ func (c *QQClient) GetFriendList() (*FriendListResponse, error) { curFriendCount := 0 r := &FriendListResponse{} for { - rsp, err := c.sendAndWait(c.buildFriendGroupListRequestPacket(int16(curFriendCount), 150, 0, 0)) + call := c.buildFriendGroupListRequest(int16(curFriendCount), 150, 0, 0) + rsp, err := c.callAndDecode(call, decodeFriendGroupListResponse) if err != nil { return nil, err } @@ -526,11 +519,11 @@ func (c *QQClient) GetFriendList() (*FriendListResponse, error) { } func (c *QQClient) SendGroupPoke(groupCode, target int64) { - _, _ = c.sendAndWait(c.buildGroupPokePacket(groupCode, target)) + _, _ = c.call(c.buildGroupPokeRequest(groupCode, target)) } func (c *QQClient) SendFriendPoke(target int64) { - _, _ = c.sendAndWait(c.buildFriendPokePacket(target)) + _, _ = c.call(c.buildFriendPokeRequest(target)) } func (c *QQClient) ReloadGroupList() error { @@ -545,7 +538,7 @@ func (c *QQClient) ReloadGroupList() error { } func (c *QQClient) GetGroupList() ([]*GroupInfo, error) { - rsp, err := c.sendAndWait(c.buildGroupListRequestPacket(EmptyBytes)) + rsp, err := c.callAndDecode(c.buildGroupListRequest(EmptyBytes), decodeGroupListResponse) if err != nil { return nil, err } @@ -577,7 +570,7 @@ func (c *QQClient) GetGroupMembers(group *GroupInfo) ([]*GroupMemberInfo, error) var nextUin int64 var list []*GroupMemberInfo for { - data, err := c.sendAndWait(c.buildGroupMemberListRequestPacket(group.Uin, group.Code, nextUin)) + data, err := c.callAndDecode(c.buildGroupMemberListRequest(group.Uin, group.Code, nextUin), decodeGroupMemberListResponse) if err != nil { return nil, err } @@ -603,7 +596,7 @@ func (c *QQClient) GetGroupMembers(group *GroupInfo) ([]*GroupMemberInfo, error) } func (c *QQClient) GetMemberInfo(groupCode, memberUin int64) (*GroupMemberInfo, error) { - info, err := c.sendAndWait(c.buildGroupMemberInfoRequestPacket(groupCode, memberUin)) + info, err := c.callAndDecode(c.buildGroupMemberInfoRequest(groupCode, memberUin), decodeGroupMemberInfoResponse) if err != nil { return nil, err } @@ -624,7 +617,7 @@ func (c *QQClient) DeleteFriend(uin int64) error { if c.FindFriend(uin) == nil { return errors.New("friend not found") } - _, err := c.sendAndWait(c.buildFriendDeletePacket(uin)) + _, err := c.callAndDecode(c.buildFriendDeletePacket(uin), decodeFriendDeleteResponse) return errors.Wrap(err, "delete friend error") } @@ -655,29 +648,28 @@ func (c *QQClient) SolveGroupJoinRequest(i interface{}, accept, block bool, reas switch req := i.(type) { case *UserJoinGroupRequest: - _, pkt := c.buildSystemMsgGroupActionPacket(req.RequestId, req.RequesterUin, req.GroupCode, func() int32 { + call := c.buildSystemMsgGroupActionPacket(req.RequestId, req.RequesterUin, req.GroupCode, func() int32 { if req.Suspicious { return 2 } else { return 1 } }(), false, accept, block, reason) - _ = c.sendPacket(pkt) + _, _ = c.call(call) case *GroupInvitedRequest: - _, pkt := c.buildSystemMsgGroupActionPacket(req.RequestId, req.InvitorUin, req.GroupCode, 1, true, accept, block, reason) - _ = c.sendPacket(pkt) + call := c.buildSystemMsgGroupActionPacket(req.RequestId, req.InvitorUin, req.GroupCode, 1, true, accept, block, reason) + _, _ = c.call(call) } } func (c *QQClient) SolveFriendRequest(req *NewFriendRequest, accept bool) { - _, pkt := c.buildSystemMsgFriendActionPacket(req.RequestId, req.RequesterUin, accept) - _ = c.sendPacket(pkt) + _, _ = c.call(c.buildSystemMsgFriendActionPacket(req.RequestId, req.RequesterUin, accept)) } func (c *QQClient) getSKey() string { if c.sig.SKeyExpiredTime < time.Now().Unix() && len(c.sig.G) > 0 { c.Debug("skey expired. refresh...") - _, _ = c.sendAndWait(c.buildRequestTgtgtNopicsigPacket()) + _, _ = c.callAndDecode(c.buildRequestTgtgtNopicsigRequest(), decodeExchangeEmpResponse) } return string(c.sig.SKey) } @@ -705,39 +697,39 @@ func (c *QQClient) getCSRFToken() int { } func (c *QQClient) editMemberCard(groupCode, memberUin int64, card string) { - _, _ = c.sendAndWait(c.buildEditGroupTagPacket(groupCode, memberUin, card)) + _, _ = c.call(c.buildEditGroupTagPacket(groupCode, memberUin, card)) } func (c *QQClient) editMemberSpecialTitle(groupCode, memberUin int64, title string) { - _, _ = c.sendAndWait(c.buildEditSpecialTitlePacket(groupCode, memberUin, title)) + _, _ = c.call(c.buildEditSpecialTitlePacket(groupCode, memberUin, title)) } func (c *QQClient) setGroupAdmin(groupCode, memberUin int64, flag bool) { - _, _ = c.sendAndWait(c.buildGroupAdminSetPacket(groupCode, memberUin, flag)) + _, _ = c.call(c.buildGroupAdminSetPacket(groupCode, memberUin, flag)) } func (c *QQClient) updateGroupName(groupCode int64, newName string) { - _, _ = c.sendAndWait(c.buildGroupNameUpdatePacket(groupCode, newName)) + _, _ = c.call(c.buildGroupNameUpdateRequest(groupCode, newName)) } func (c *QQClient) updateGroupMemo(groupCode int64, newMemo string) { - _, _ = c.sendAndWait(c.buildGroupMemoUpdatePacket(groupCode, newMemo)) + _, _ = c.call(c.buildGroupMemoUpdatePacket(groupCode, newMemo)) } func (c *QQClient) groupMuteAll(groupCode int64, mute bool) { - _, _ = c.sendAndWait(c.buildGroupMuteAllPacket(groupCode, mute)) + _, _ = c.call(c.buildGroupMuteAllPacket(groupCode, mute)) } func (c *QQClient) groupMute(groupCode, memberUin int64, time uint32) { - _, _ = c.sendAndWait(c.buildGroupMutePacket(groupCode, memberUin, time)) + _, _ = c.call(c.buildGroupMutePacket(groupCode, memberUin, time)) } func (c *QQClient) quitGroup(groupCode int64) { - _, _ = c.sendAndWait(c.buildQuitGroupPacket(groupCode)) + _, _ = c.call(c.buildQuitGroupPacket(groupCode)) } func (c *QQClient) kickGroupMember(groupCode, memberUin int64, msg string, block bool) { - _, _ = c.sendAndWait(c.buildGroupKickPacket(groupCode, memberUin, msg, block)) + _, _ = c.call(c.buildGroupKickPacket(groupCode, memberUin, msg, block)) } func (g *GroupInfo) removeMember(uin int64) { @@ -757,7 +749,7 @@ func (c *QQClient) SetCustomServer(servers []*net.TCPAddr) { } func (c *QQClient) registerClient() error { - _, err := c.sendAndWait(c.buildClientRegisterPacket()) + _, err := c.callAndDecode(c.buildClientRegisterPacket(), decodeClientRegisterResponse) if err == nil { c.Online.Store(true) } diff --git a/client/decoders.go b/client/decoders.go index 4cd40451..10813e0a 100644 --- a/client/decoders.go +++ b/client/decoders.go @@ -148,7 +148,7 @@ func decodeLoginResponse(c *QQClient, resp *network.Response) (interface{}, erro if t == 204 { c.sig.T104 = m[0x104] c.sig.RandSeed = m[0x403] - return c.sendAndWait(c.buildDeviceLockLoginPacket()) + return c.callAndDecode(c.buildDeviceLockLoginRequest(), decodeLoginResponse) } // drive lock if t149, ok := m[0x149]; ok { @@ -365,8 +365,8 @@ func decodePushReqPacket(c *QQClient, resp *network.Response) (interface{}, erro } seq := r.ReadInt64(3) - _, pkt := c.buildConfPushRespPacket(t, seq, jceBuf) - return nil, c.sendPacket(pkt) + err := c.sendPacket(c.transport.PackPacket(c.buildConfPushRespPacket(t, seq, jceBuf))) + return nil, err } // MessageSvc.PbGetMsg @@ -399,8 +399,8 @@ func decodeSvcNotify(c *QQClient, resp *network.Response) (interface{}, error) { return nil, nil } if typ == sysMsgDecoders { - _, pkt := c.buildSystemMsgNewFriendPacket() - return nil, c.sendPacket(pkt) + _, err := c.callAndDecode(c.buildSystemMsgNewFriendRequest(), decodeSystemMsgFriendPacket) + return nil, err } } _, err := c.sendAndWait(c.buildGetMessageRequestPacket(msg.SyncFlag_START, time.Now().Unix())) @@ -516,7 +516,7 @@ func decodeGroupListResponse(c *QQClient, resp *network.Response) (interface{}, }) } if len(vecCookie) > 0 { - rsp, err := c.sendAndWait(c.buildGroupListRequestPacket(vecCookie)) + rsp, err := c.callAndDecode(c.buildGroupListRequest(vecCookie), decodeGroupListResponse) if err != nil { return nil, err } @@ -796,14 +796,14 @@ func decodeWordSegmentation(_ *QQClient, resp *network.Response) (interface{}, e } func decodeSidExpiredPacket(c *QQClient, resp *network.Response) (interface{}, error) { - _, err := c.sendAndWait(c.buildRequestChangeSigPacket(3554528)) + _, err := c.callAndDecode(c.buildRequestChangeSigRequest(3554528), decodeExchangeEmpResponse) if err != nil { return nil, errors.Wrap(err, "resign client error") } if err = c.registerClient(); err != nil { return nil, errors.Wrap(err, "register error") } - _ = c.sendPacket(c.uniPacketWithSeq(uint16(resp.SequenceID), "OnlinePush.SidTicketExpired", EmptyBytes)) + _, _ = c.call(c.uniPacketWithSeq(uint16(resp.SequenceID), "OnlinePush.SidTicketExpired", EmptyBytes)) return nil, nil } diff --git a/client/face.go b/client/face.go index 0f30f1c6..f095fdaa 100644 --- a/client/face.go +++ b/client/face.go @@ -15,19 +15,15 @@ type CustomFace struct { Url string } -func init() { - decoders["Faceroam.OpReq"] = decodeFaceroamResponse -} - func (c *QQClient) GetCustomFaces() ([]*CustomFace, error) { - i, err := c.sendAndWait(c.buildFaceroamRequestPacket()) + i, err := c.callAndDecode(c.buildFaceroamRequestPacket(), decodeFaceroamResponse) if err != nil { return nil, errors.Wrap(err, "get faces error") } return i.([]*CustomFace), nil } -func (c *QQClient) buildFaceroamRequestPacket() (uint16, []byte) { +func (c *QQClient) buildFaceroamRequestPacket() *network.Request { payload, _ := proto.Marshal(&faceroam.FaceroamReqBody{ Comm: &faceroam.PlatInfo{ Implat: proto.Int64(109), @@ -38,7 +34,7 @@ func (c *QQClient) buildFaceroamRequestPacket() (uint16, []byte) { SubCmd: proto.Uint32(1), ReqUserInfo: &faceroam.ReqUserInfo{}, }) - return c.uniPacket("Faceroam.OpReq", payload) + return c.uniRequest("Faceroam.OpReq", payload) } func decodeFaceroamResponse(c *QQClient, resp *network.Response) (interface{}, error) { diff --git a/client/group_file.go b/client/group_file.go index 8a653832..a17a647d 100644 --- a/client/group_file.go +++ b/client/group_file.go @@ -57,17 +57,6 @@ type ( var fsWaiter = utils.NewUploadWaiter() -func init() { - decoders["OidbSvc.0x6d8_1"] = decodeOIDB6d81Response - decoders["OidbSvc.0x6d6_0"] = decodeOIDB6d60Response - decoders["OidbSvc.0x6d6_2"] = decodeOIDB6d62Response - decoders["OidbSvc.0x6d6_3"] = decodeOIDB6d63Response - decoders["OidbSvc.0x6d7_0"] = decodeOIDB6d7Response - decoders["OidbSvc.0x6d7_1"] = decodeOIDB6d7Response - decoders["OidbSvc.0x6d7_2"] = decodeOIDB6d7Response - decoders["OidbSvc.0x6d9_4"] = ignoreDecoder -} - func (c *QQClient) GetGroupFileSystem(groupCode int64) (fs *GroupFileSystem, err error) { defer func() { if pan := recover(); pan != nil { @@ -79,7 +68,7 @@ func (c *QQClient) GetGroupFileSystem(groupCode int64) (fs *GroupFileSystem, err if g == nil { return nil, errors.New("group not found") } - rsp, e := c.sendAndWait(c.buildGroupFileCountRequestPacket(groupCode)) + rsp, e := c.callAndDecode(c.buildGroupFileCountRequest(groupCode), decodeOIDB6d81Response) if e != nil { return nil, e } @@ -89,7 +78,7 @@ func (c *QQClient) GetGroupFileSystem(groupCode int64) (fs *GroupFileSystem, err GroupCode: groupCode, client: c, } - rsp, err = c.sendAndWait(c.buildGroupFileSpaceRequestPacket(groupCode)) + rsp, err = c.callAndDecode(c.buildGroupFileSpaceRequest(groupCode), decodeOIDB6d81Response) if err != nil { return nil, err } @@ -99,7 +88,7 @@ func (c *QQClient) GetGroupFileSystem(groupCode int64) (fs *GroupFileSystem, err } func (c *QQClient) GetGroupFileUrl(groupCode int64, fileId string, busId int32) string { - i, err := c.sendAndWait(c.buildGroupFileDownloadReqPacket(groupCode, fileId, busId)) + i, err := c.callAndDecode(c.buildGroupFileDownloadReq(groupCode, fileId, busId), decodeOIDB6d62Response) if err != nil { return "" } @@ -117,7 +106,8 @@ func (fs *GroupFileSystem) GetFilesByFolder(folderID string) ([]*GroupFile, []*G var files []*GroupFile var folders []*GroupFolder for { - i, err := fs.client.sendAndWait(fs.client.buildGroupFileListRequestPacket(fs.GroupCode, folderID, startIndex)) + req := fs.client.buildGroupFileListRequest(fs.GroupCode, folderID, startIndex) + i, err := fs.client.callAndDecode(req, decodeOIDB6d81Response) if err != nil { return nil, nil, err } @@ -177,14 +167,16 @@ func (fs *GroupFileSystem) UploadFile(p, name, folderId string) error { _, _ = io.Copy(sha1H, file) sha1Hash := sha1H.Sum(nil) _, _ = file.Seek(0, io.SeekStart) - i, err := fs.client.sendAndWait(fs.client.buildGroupFileUploadReqPacket(folderId, name, fs.GroupCode, size, md5Hash, sha1Hash)) + req := fs.client.buildGroupFileUploadReq(folderId, name, fs.GroupCode, size, md5Hash, sha1Hash) + i, err := fs.client.callAndDecode(req, decodeOIDB6d60Response) if err != nil { return errors.Wrap(err, "query upload failed") } rsp := i.(*oidb.UploadFileRspBody) if rsp.GetBoolFileExist() { - _, pkt := fs.client.buildGroupFileFeedsRequest(fs.GroupCode, rsp.GetFileId(), rsp.GetBusId(), rand.Int31()) - return fs.client.sendPacket(pkt) + req := fs.client.buildGroupFileFeedsRequest(fs.GroupCode, rsp.GetFileId(), rsp.GetBusId(), rand.Int31()) + _, err := fs.client.call(req) + return err } if len(rsp.UploadIpLanV4) == 0 { return errors.New("server requires unsupported ftn upload") @@ -236,8 +228,9 @@ func (fs *GroupFileSystem) UploadFile(p, name, folderId string) error { if _, err = fs.client.highwaySession.UploadExciting(input); err != nil { return errors.Wrap(err, "upload failed") } - _, pkt := client.buildGroupFileFeedsRequest(fs.GroupCode, rsp.GetFileId(), rsp.GetBusId(), rand.Int31()) - return client.sendPacket(pkt) + req = client.buildGroupFileFeedsRequest(fs.GroupCode, rsp.GetFileId(), rsp.GetBusId(), rand.Int31()) + _, err = client.call(req) + return err } func (fs *GroupFileSystem) GetDownloadUrl(file *GroupFile) string { @@ -245,21 +238,21 @@ func (fs *GroupFileSystem) GetDownloadUrl(file *GroupFile) string { } func (fs *GroupFileSystem) CreateFolder(parentFolder, name string) error { - if _, err := fs.client.sendAndWait(fs.client.buildGroupFileCreateFolderPacket(fs.GroupCode, parentFolder, name)); err != nil { + if _, err := fs.client.callAndDecode(fs.client.buildGroupFileCreateFolderRequest(fs.GroupCode, parentFolder, name), decodeOIDB6d7Response); err != nil { return errors.Wrap(err, "create folder error") } return nil } func (fs *GroupFileSystem) RenameFolder(folderId, newName string) error { - if _, err := fs.client.sendAndWait(fs.client.buildGroupFileRenameFolderPacket(fs.GroupCode, folderId, newName)); err != nil { + if _, err := fs.client.callAndDecode(fs.client.buildGroupFileRenameFolderRequest(fs.GroupCode, folderId, newName), decodeOIDB6d7Response); err != nil { return errors.Wrap(err, "rename folder error") } return nil } func (fs *GroupFileSystem) DeleteFolder(folderId string) error { - if _, err := fs.client.sendAndWait(fs.client.buildGroupFileDeleteFolderPacket(fs.GroupCode, folderId)); err != nil { + if _, err := fs.client.callAndDecode(fs.client.buildGroupFileDeleteFolderRequest(fs.GroupCode, folderId), decodeOIDB6d7Response); err != nil { return errors.Wrap(err, "rename folder error") } return nil @@ -268,14 +261,14 @@ func (fs *GroupFileSystem) DeleteFolder(folderId string) error { // DeleteFile 删除群文件,需要管理权限. // 返回错误, 空为删除成功 func (fs *GroupFileSystem) DeleteFile(parentFolderID, fileId string, busId int32) string { - i, err := fs.client.sendAndWait(fs.client.buildGroupFileDeleteReqPacket(fs.GroupCode, parentFolderID, fileId, busId)) + i, err := fs.client.callAndDecode(fs.client.buildGroupFileDeleteReq(fs.GroupCode, parentFolderID, fileId, busId), decodeOIDB6d63Response) if err != nil { return err.Error() } return i.(string) } -func (c *QQClient) buildGroupFileUploadReqPacket(parentFolderID, fileName string, groupCode, fileSize int64, md5, sha1 []byte) (uint16, []byte) { +func (c *QQClient) buildGroupFileUploadReq(parentFolderID, fileName string, groupCode, fileSize int64, md5, sha1 []byte) *network.Request { b, _ := proto.Marshal(&oidb.D6D6ReqBody{UploadFileReq: &oidb.UploadFileReqBody{ GroupCode: &groupCode, AppId: proto.Int32(3), @@ -296,10 +289,10 @@ func (c *QQClient) buildGroupFileUploadReqPacket(parentFolderID, fileName string ClientVersion: "android 8.4.8", } payload, _ := proto.Marshal(req) - return c.uniPacket("OidbSvc.0x6d6_0", payload) + return c.uniRequest("OidbSvc.0x6d6_0", payload) } -func (c *QQClient) buildGroupFileFeedsRequest(groupCode int64, fileID string, busId, msgRand int32) (uint16, []byte) { +func (c *QQClient) buildGroupFileFeedsRequest(groupCode int64, fileID string, busId, msgRand int32) *network.Request { req := c.packOIDBPackageProto(1753, 4, &oidb.D6D9ReqBody{FeedsInfoReq: &oidb.FeedsReqBody{ GroupCode: proto.Uint64(uint64(groupCode)), AppId: proto.Uint32(3), @@ -310,11 +303,11 @@ func (c *QQClient) buildGroupFileFeedsRequest(groupCode int64, fileID string, bu MsgRandom: proto.Uint32(uint32(msgRand)), }}, }}) - return c.uniPacket("OidbSvc.0x6d9_4", req) + return c.uniRequest("OidbSvc.0x6d9_4", req) } // OidbSvc.0x6d8_1 -func (c *QQClient) buildGroupFileListRequestPacket(groupCode int64, folderID string, startIndex uint32) (uint16, []byte) { +func (c *QQClient) buildGroupFileListRequest(groupCode int64, folderID string, startIndex uint32) *network.Request { body := &oidb.D6D8ReqBody{FileListInfoReq: &oidb.GetFileListReqBody{ GroupCode: proto.Uint64(uint64(groupCode)), AppId: proto.Uint32(3), @@ -336,10 +329,10 @@ func (c *QQClient) buildGroupFileListRequestPacket(groupCode int64, folderID str ClientVersion: "android 8.4.8", } payload, _ := proto.Marshal(req) - return c.uniPacket("OidbSvc.0x6d8_1", payload) + return c.uniRequest("OidbSvc.0x6d8_1", payload) } -func (c *QQClient) buildGroupFileCountRequestPacket(groupCode int64) (uint16, []byte) { +func (c *QQClient) buildGroupFileCountRequest(groupCode int64) *network.Request { body := &oidb.D6D8ReqBody{GroupFileCountReq: &oidb.GetFileCountReqBody{ GroupCode: proto.Uint64(uint64(groupCode)), AppId: proto.Uint32(3), @@ -353,10 +346,10 @@ func (c *QQClient) buildGroupFileCountRequestPacket(groupCode int64) (uint16, [] ClientVersion: "android 8.4.8", } payload, _ := proto.Marshal(req) - return c.uniPacket("OidbSvc.0x6d8_1", payload) + return c.uniRequest("OidbSvc.0x6d8_1", payload) } -func (c *QQClient) buildGroupFileSpaceRequestPacket(groupCode int64) (uint16, []byte) { +func (c *QQClient) buildGroupFileSpaceRequest(groupCode int64) *network.Request { body := &oidb.D6D8ReqBody{GroupSpaceReq: &oidb.GetSpaceReqBody{ GroupCode: proto.Uint64(uint64(groupCode)), AppId: proto.Uint32(3), @@ -369,40 +362,40 @@ func (c *QQClient) buildGroupFileSpaceRequestPacket(groupCode int64) (uint16, [] ClientVersion: "android 8.4.8", } payload, _ := proto.Marshal(req) - return c.uniPacket("OidbSvc.0x6d8_1", payload) + return c.uniRequest("OidbSvc.0x6d8_1", payload) } -func (c *QQClient) buildGroupFileCreateFolderPacket(groupCode int64, parentFolder, name string) (uint16, []byte) { +func (c *QQClient) buildGroupFileCreateFolderRequest(groupCode int64, parentFolder, name string) *network.Request { payload := c.packOIDBPackageProto(1751, 0, &oidb.D6D7ReqBody{CreateFolderReq: &oidb.CreateFolderReqBody{ GroupCode: proto.Uint64(uint64(groupCode)), AppId: proto.Uint32(3), ParentFolderId: &parentFolder, FolderName: &name, }}) - return c.uniPacket("OidbSvc.0x6d7_0", payload) + return c.uniRequest("OidbSvc.0x6d7_0", payload) } -func (c *QQClient) buildGroupFileRenameFolderPacket(groupCode int64, folderId, newName string) (uint16, []byte) { +func (c *QQClient) buildGroupFileRenameFolderRequest(groupCode int64, folderId, newName string) *network.Request { payload := c.packOIDBPackageProto(1751, 2, &oidb.D6D7ReqBody{RenameFolderReq: &oidb.RenameFolderReqBody{ GroupCode: proto.Uint64(uint64(groupCode)), AppId: proto.Uint32(3), FolderId: proto.String(folderId), NewFolderName: proto.String(newName), }}) - return c.uniPacket("OidbSvc.0x6d7_2", payload) + return c.uniRequest("OidbSvc.0x6d7_2", payload) } -func (c *QQClient) buildGroupFileDeleteFolderPacket(groupCode int64, folderId string) (uint16, []byte) { +func (c *QQClient) buildGroupFileDeleteFolderRequest(groupCode int64, folderId string) *network.Request { payload := c.packOIDBPackageProto(1751, 1, &oidb.D6D7ReqBody{DeleteFolderReq: &oidb.DeleteFolderReqBody{ GroupCode: proto.Uint64(uint64(groupCode)), AppId: proto.Uint32(3), FolderId: proto.String(folderId), }}) - return c.uniPacket("OidbSvc.0x6d7_1", payload) + return c.uniRequest("OidbSvc.0x6d7_1", payload) } // OidbSvc.0x6d6_2 -func (c *QQClient) buildGroupFileDownloadReqPacket(groupCode int64, fileId string, busId int32) (uint16, []byte) { +func (c *QQClient) buildGroupFileDownloadReq(groupCode int64, fileId string, busId int32) *network.Request { body := &oidb.D6D6ReqBody{ DownloadFileReq: &oidb.DownloadFileReqBody{ GroupCode: &groupCode, @@ -418,10 +411,10 @@ func (c *QQClient) buildGroupFileDownloadReqPacket(groupCode int64, fileId strin Bodybuffer: b, } payload, _ := proto.Marshal(req) - return c.uniPacket("OidbSvc.0x6d6_2", payload) + return c.uniRequest("OidbSvc.0x6d6_2", payload) } -func (c *QQClient) buildGroupFileDeleteReqPacket(groupCode int64, parentFolderId, fileId string, busId int32) (uint16, []byte) { +func (c *QQClient) buildGroupFileDeleteReq(groupCode int64, parentFolderId, fileId string, busId int32) *network.Request { body := &oidb.D6D6ReqBody{DeleteFileReq: &oidb.DeleteFileReqBody{ GroupCode: &groupCode, AppId: proto.Int32(3), @@ -437,7 +430,7 @@ func (c *QQClient) buildGroupFileDeleteReqPacket(groupCode int64, parentFolderId ClientVersion: "android 8.4.8", } payload, _ := proto.Marshal(req) - return c.uniPacket("OidbSvc.0x6d6_3", payload) + return c.uniRequest("OidbSvc.0x6d6_3", payload) } func decodeOIDB6d81Response(_ *QQClient, resp *network.Response) (interface{}, error) { diff --git a/client/group_info.go b/client/group_info.go index 37bb8bc3..f99265fc 100644 --- a/client/group_info.go +++ b/client/group_info.go @@ -65,13 +65,8 @@ type ( } ) -func init() { - decoders["SummaryCard.ReqSearch"] = decodeGroupSearchResponse - decoders["OidbSvc.0x88d_0"] = decodeGroupInfoResponse -} - func (c *QQClient) GetGroupInfo(groupCode int64) (*GroupInfo, error) { - i, err := c.sendAndWait(c.buildGroupInfoRequestPacket(groupCode)) + i, err := c.callAndDecode(c.buildGroupInfoRequestPacket(groupCode), decodeGroupInfoResponse) if err != nil { return nil, err } @@ -79,7 +74,7 @@ func (c *QQClient) GetGroupInfo(groupCode int64) (*GroupInfo, error) { } // OidbSvc.0x88d_0 -func (c *QQClient) buildGroupInfoRequestPacket(groupCode int64) (uint16, []byte) { +func (c *QQClient) buildGroupInfoRequestPacket(groupCode int64) *network.Request { body := &oidb.D88DReqBody{ AppId: proto.Uint32(c.version.AppId), ReqGroupInfo: []*oidb.ReqGroupInfo{ @@ -122,12 +117,12 @@ func (c *QQClient) buildGroupInfoRequestPacket(groupCode int64) (uint16, []byte) Bodybuffer: b, } payload, _ := proto.Marshal(req) - return c.uniPacket("OidbSvc.0x88d_0", payload) + return c.uniRequest("OidbSvc.0x88d_0", payload) } // SearchGroupByKeyword 通过关键词搜索陌生群组 func (c *QQClient) SearchGroupByKeyword(keyword string) ([]GroupSearchInfo, error) { - rsp, err := c.sendAndWait(c.buildGroupSearchPacket(keyword)) + rsp, err := c.callAndDecode(c.buildGroupSearchPacket(keyword), decodeGroupSearchResponse) if err != nil { return nil, errors.Wrap(err, "group search failed") } @@ -135,7 +130,7 @@ func (c *QQClient) SearchGroupByKeyword(keyword string) ([]GroupSearchInfo, erro } // SummaryCard.ReqSearch -func (c *QQClient) buildGroupSearchPacket(keyword string) (uint16, []byte) { +func (c *QQClient) buildGroupSearchPacket(keyword string) *network.Request { comm, _ := proto.Marshal(&profilecard.BusiComm{ Ver: proto.Int32(1), Seq: proto.Int32(rand.Int31()), @@ -184,7 +179,7 @@ func (c *QQClient) buildGroupSearchPacket(keyword string) (uint16, []byte) { Context: make(map[string]string), Status: make(map[string]string), } - return c.uniPacket("SummaryCard.ReqSearch", pkt.ToBytes()) + return c.uniRequest("SummaryCard.ReqSearch", pkt.ToBytes()) } // SummaryCard.ReqSearch diff --git a/client/group_msg.go b/client/group_msg.go index ec769e7c..846c27bd 100644 --- a/client/group_msg.go +++ b/client/group_msg.go @@ -28,9 +28,6 @@ func init() { decoders["OnlinePush.PbPushGroupMsg"] = decodeGroupMessagePacket decoders["MessageSvc.PbSendMsg"] = decodeMsgSendResponse decoders["MessageSvc.PbGetGroupMsg"] = decodeGetGroupMsgResponse - decoders["OidbSvc.0x8a7_0"] = decodeAtAllRemainResponse - decoders["OidbSvc.0xeac_1"] = decodeEssenceMsgResponse - decoders["OidbSvc.0xeac_2"] = decodeEssenceMsgResponse } // SendGroupMessage 发送群消息 @@ -80,8 +77,8 @@ func (c *QQClient) SendGroupForwardMessage(groupCode int64, m *message.ForwardEl // GetGroupMessages 从服务器获取历史信息 func (c *QQClient) GetGroupMessages(groupCode, beginSeq, endSeq int64) ([]*message.GroupMessage, error) { - seq, pkt := c.buildGetGroupMsgRequest(groupCode, beginSeq, endSeq) - i, err := c.sendAndWaitParams(seq, pkt, network.RequestParams{"raw": false}) + req := c.buildGetGroupMsgRequest(groupCode, beginSeq, endSeq) + i, err := c.sendAndWaitParams(uint16(req.SequenceID), c.transport.PackPacket(req), network.RequestParams{"raw": false}) if err != nil { return nil, err } @@ -89,7 +86,7 @@ func (c *QQClient) GetGroupMessages(groupCode, beginSeq, endSeq int64) ([]*messa } func (c *QQClient) GetAtAllRemain(groupCode int64) (*AtAllRemainInfo, error) { - i, err := c.sendAndWait(c.buildAtAllRemainRequestPacket(groupCode)) + i, err := c.callAndDecode(c.buildAtAllRemainRequestPacket(groupCode), decodeAtAllRemainResponse) if err != nil { return nil, err } @@ -123,12 +120,12 @@ func (c *QQClient) sendGroupMessage(groupCode int64, forward bool, m *message.Se div := int32(rand.Uint32()) fragmented := m.ToFragmented() for i, elems := range fragmented { - _, pkt := c.buildGroupSendingPacket(groupCode, mr, int32(len(fragmented)), int32(i), div, forward, elems) - _ = c.sendPacket(pkt) + req := c.buildGroupSendingReq(groupCode, mr, int32(len(fragmented)), int32(i), div, forward, elems) + c.sendReq(req) } } else { - _, pkt := c.buildGroupSendingPacket(groupCode, mr, 1, 0, 0, forward, m.Elements) - _ = c.sendPacket(pkt) + req := c.buildGroupSendingReq(groupCode, mr, 1, 0, 0, forward, m.Elements) + c.sendReq(req) } var mid int32 ret := &message.GroupMessage{ @@ -214,7 +211,7 @@ func (c *QQClient) UploadGroupForwardMessage(groupCode int64, m *message.Forward } func (c *QQClient) multiMsgApplyUp(groupCode int64, data []byte, hash []byte, buType int32) (*multimsg.MultiMsgApplyUpRsp, []byte, error) { - i, err := c.sendAndWait(c.buildMultiApplyUpPacket(data, hash, buType, utils.ToGroupUin(groupCode))) + i, err := c.callAndDecode(c.buildMultiApplyUpPacket(data, hash, buType, utils.ToGroupUin(groupCode)), decodeMultiApplyUpResponse) if err != nil { return nil, nil, err } @@ -237,7 +234,7 @@ func (c *QQClient) multiMsgApplyUp(groupCode int64, data []byte, hash []byte, bu } // MessageSvc.PbSendMsg -func (c *QQClient) buildGroupSendingPacket(groupCode int64, r, pkgNum, pkgIndex, pkgDiv int32, forward bool, m []message.IMessageElement) (uint16, []byte) { +func (c *QQClient) buildGroupSendingReq(groupCode int64, r, pkgNum, pkgIndex, pkgDiv int32, forward bool, m []message.IMessageElement) *network.Request { var ptt *message.GroupVoiceElement if len(m) > 0 { if p, ok := m[0].(*message.GroupVoiceElement); ok { @@ -271,10 +268,10 @@ func (c *QQClient) buildGroupSendingPacket(groupCode int64, r, pkgNum, pkgIndex, }(), } payload, _ := proto.Marshal(req) - return c.uniPacket("MessageSvc.PbSendMsg", payload) + return c.uniRequest("MessageSvc.PbSendMsg", payload) } -func (c *QQClient) buildGetGroupMsgRequest(groupCode, beginSeq, endSeq int64) (uint16, []byte) { +func (c *QQClient) buildGetGroupMsgRequest(groupCode, beginSeq, endSeq int64) *network.Request { req := &msg.GetGroupMsgReq{ GroupCode: proto.Uint64(uint64(groupCode)), BeginSeq: proto.Uint64(uint64(beginSeq)), @@ -282,10 +279,10 @@ func (c *QQClient) buildGetGroupMsgRequest(groupCode, beginSeq, endSeq int64) (u PublicGroup: proto.Bool(false), } payload, _ := proto.Marshal(req) - return c.uniPacket("MessageSvc.PbGetGroupMsg", payload) + return c.uniRequest("MessageSvc.PbGetGroupMsg", payload) } -func (c *QQClient) buildAtAllRemainRequestPacket(groupCode int64) (uint16, []byte) { +func (c *QQClient) buildAtAllRemainRequestPacket(groupCode int64) *network.Request { payload := c.packOIDBPackageProto(2215, 0, &oidb.D8A7ReqBody{ SubCmd: proto.Uint32(1), LimitIntervalTypeForUin: proto.Uint32(2), @@ -293,7 +290,7 @@ func (c *QQClient) buildAtAllRemainRequestPacket(groupCode int64) (uint16, []byt Uin: proto.Uint64(uint64(c.Uin)), GroupCode: proto.Uint64(uint64(groupCode)), }) - return c.uniPacket("OidbSvc.0x8a7_0", payload) + return c.uniRequest("OidbSvc.0x8a7_0", payload) } // OnlinePush.PbPushGroupMsg @@ -374,8 +371,8 @@ func decodeGetGroupMsgResponse(c *QQClient, resp *network.Response) (interface{} builder := &groupMessageBuilder{} for { end := int32(math.Min(float64(i+19), float64(m.Head.GetMsgSeq()+m.Content.GetPkgNum()))) - seq, pkt := c.buildGetGroupMsgRequest(m.Head.GroupInfo.GetGroupCode(), int64(i), int64(end)) - data, err := c.sendAndWaitParams(seq, pkt, network.RequestParams{"raw": true}) + req := c.buildGetGroupMsgRequest(m.Head.GroupInfo.GetGroupCode(), int64(i), int64(end)) + data, err := c.sendAndWaitParams(uint16(req.SequenceID), c.transport.PackPacket(req), network.RequestParams{"raw": true}) if err != nil { return nil, errors.Wrap(err, "build fragmented message error") } @@ -563,7 +560,7 @@ func (c *QQClient) parseGroupMessage(m *msg.Message) *message.GroupMessage { // SetEssenceMessage 设为群精华消息 func (c *QQClient) SetEssenceMessage(groupCode int64, msgID, msgInternalId int32) error { - r, err := c.sendAndWait(c.buildEssenceMsgOperatePacket(groupCode, uint32(msgID), uint32(msgInternalId), 1)) + r, err := c.callAndDecode(c.buildEssenceMsgOperatePacket(groupCode, uint32(msgID), uint32(msgInternalId), 1), decodeEssenceMsgResponse) if err != nil { return errors.Wrap(err, "set essence msg network") } @@ -576,7 +573,7 @@ func (c *QQClient) SetEssenceMessage(groupCode int64, msgID, msgInternalId int32 // DeleteEssenceMessage 移出群精华消息 func (c *QQClient) DeleteEssenceMessage(groupCode int64, msgID, msgInternalId int32) error { - r, err := c.sendAndWait(c.buildEssenceMsgOperatePacket(groupCode, uint32(msgID), uint32(msgInternalId), 2)) + r, err := c.callAndDecode(c.buildEssenceMsgOperatePacket(groupCode, uint32(msgID), uint32(msgInternalId), 2), decodeEssenceMsgResponse) if err != nil { return errors.Wrap(err, "set essence msg networ") } @@ -587,14 +584,14 @@ func (c *QQClient) DeleteEssenceMessage(groupCode int64, msgID, msgInternalId in return nil } -func (c *QQClient) buildEssenceMsgOperatePacket(groupCode int64, msgSeq, msgRand, opType uint32) (uint16, []byte) { +func (c *QQClient) buildEssenceMsgOperatePacket(groupCode int64, msgSeq, msgRand, opType uint32) *network.Request { commandName := "OidbSvc.0xeac_" + strconv.FormatInt(int64(opType), 10) payload := c.packOIDBPackageProto(3756, int32(opType), &oidb.EACReqBody{ // serviceType 2 取消 GroupCode: proto.Uint64(uint64(groupCode)), Seq: proto.Uint32(msgSeq), Random: proto.Uint32(msgRand), }) - return c.uniPacket(commandName, payload) + return c.uniRequest(commandName, payload) } // OidbSvc.0xeac_1/2 diff --git a/client/guild.go b/client/guild.go index 82f13fd8..8224e5a5 100644 --- a/client/guild.go +++ b/client/guild.go @@ -187,12 +187,12 @@ func (s *GuildService) GetUserProfile(tinyId uint64) (*GuildUserProfile, error) 3: tinyId, 4: uint32(0), }) - rsp, err := s.c.sendAndWaitDynamic(s.c.uniPacket("OidbSvcTrpcTcp.0xfc9_1", payload)) + rsp, err := s.c.commandCall("OidbSvcTrpcTcp.0xfc9_1", payload) if err != nil { return nil, errors.Wrap(err, "send packet error") } body := new(channel.ChannelOidb0Xfc9Rsp) - if err = unpackOIDBPackage(rsp, body); err != nil { + if err = unpackOIDBPackage(rsp.Body, body); err != nil { return nil, errors.Wrap(err, "decode packet error") } // todo: 解析个性档案 @@ -208,7 +208,6 @@ func (s *GuildService) GetUserProfile(tinyId uint64) (*GuildUserProfile, error) // 第一次请求: 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) m := binary.DynamicProtoMessage{ 1: guildId, // guild id @@ -225,13 +224,12 @@ func (s *GuildService) FetchGuildMemberListWithRole(guildId, channelId uint64, s m[13] = param } m[14] = roleIdIndex - packet := s.c.uniPacketWithSeq(seq, "OidbSvcTrpcTcp.0xf5b_1", s.c.packOIDBPackageDynamically(3931, 1, m)) - rsp, err := s.c.sendAndWaitDynamic(seq, packet) + rsp, err := s.c.commandCall("OidbSvcTrpcTcp.0xf5b_1", s.c.packOIDBPackageDynamically(3931, 1, m)) if err != nil { return nil, errors.Wrap(err, "send packet error") } body := new(channel.ChannelOidb0Xf5BRsp) - if err = unpackOIDBPackage(rsp, body); err != nil { + if err = unpackOIDBPackage(rsp.Body, body); err != nil { return nil, errors.Wrap(err, "decode packet error") } var ret []*GuildMemberInfo @@ -268,7 +266,6 @@ func (s *GuildService) FetchGuildMemberListWithRole(guildId, channelId uint64, s // FetchGuildMemberProfileInfo 获取单个频道成员资料 func (s *GuildService) FetchGuildMemberProfileInfo(guildId, tinyId uint64) (*GuildUserProfile, error) { - seq := s.c.nextSeq() flags := binary.DynamicProtoMessage{} for i := 3; i <= 29; i++ { flags[uint64(i)] = uint32(1) @@ -280,13 +277,12 @@ func (s *GuildService) FetchGuildMemberProfileInfo(guildId, tinyId uint64) (*Gui 3: tinyId, 4: guildId, }) - packet := s.c.uniPacketWithSeq(seq, "OidbSvcTrpcTcp.0xf88_1", payload) - rsp, err := s.c.sendAndWaitDynamic(seq, packet) + rsp, err := s.c.commandCall("OidbSvcTrpcTcp.0xf88_1", payload) if err != nil { return nil, errors.Wrap(err, "send packet error") } body := new(channel.ChannelOidb0Xf88Rsp) - if err = unpackOIDBPackage(rsp, body); err != nil { + if err = unpackOIDBPackage(rsp.Body, body); err != nil { return nil, errors.Wrap(err, "decode packet error") } roles, err := s.fetchMemberRoles(guildId, tinyId) @@ -304,14 +300,14 @@ func (s *GuildService) FetchGuildMemberProfileInfo(guildId, tinyId uint64) (*Gui } func (s *GuildService) GetGuildRoles(guildId uint64) ([]*GuildRole, error) { - seq, packet := s.c.uniPacket("OidbSvcTrpcTcp.0x1019_1", + req := s.c.uniRequest("OidbSvcTrpcTcp.0x1019_1", s.c.packOIDBPackageDynamically(4121, 1, binary.DynamicProtoMessage{1: guildId})) - rsp, err := s.c.sendAndWaitDynamic(seq, packet) + rsp, err := s.c.call(req) if err != nil { return nil, errors.Wrap(err, "send packet error") } body := new(channel.ChannelOidb0X1019Rsp) - if err = unpackOIDBPackage(rsp, body); err != nil { + if err = unpackOIDBPackage(rsp.Body, body); err != nil { return nil, errors.Wrap(err, "decode packet error") } roles := make([]*GuildRole, 0, len(body.GetRoles())) @@ -332,7 +328,7 @@ func (s *GuildService) GetGuildRoles(guildId uint64) ([]*GuildRole, error) { func (s *GuildService) CreateGuildRole(guildId uint64, name string, color uint32, independent bool, initialUsers []uint64) (uint64, error) { u1 := uint32(1) - seq, packet := s.c.uniPacket("OidbSvcTrpcTcp.0x1016_1", s.c.packOIDBPackageDynamically(4118, 1, binary.DynamicProtoMessage{ + req := s.c.uniRequest("OidbSvcTrpcTcp.0x1016_1", s.c.packOIDBPackageDynamically(4118, 1, binary.DynamicProtoMessage{ 1: guildId, 2: binary.DynamicProtoMessage{ // todo: 未知参数 1: u1, @@ -346,23 +342,23 @@ func (s *GuildService) CreateGuildRole(guildId uint64, name string, color uint32 }, 4: initialUsers, })) - rsp, err := s.c.sendAndWaitDynamic(seq, packet) + rsp, err := s.c.call(req) if err != nil { return 0, errors.Wrap(err, "send packet error") } body := new(channel.ChannelOidb0X1016Rsp) - if err = unpackOIDBPackage(rsp, body); err != nil { + if err = unpackOIDBPackage(rsp.Body, body); err != nil { return 0, errors.Wrap(err, "decode packet error") } return body.GetRoleId(), nil } func (s *GuildService) DeleteGuildRole(guildId uint64, roleId uint64) error { - seq, packet := s.c.uniPacket("OidbSvcTrpcTcp.0x100e_1", s.c.packOIDBPackageDynamically(4110, 1, binary.DynamicProtoMessage{ + req := s.c.uniRequest("OidbSvcTrpcTcp.0x100e_1", s.c.packOIDBPackageDynamically(4110, 1, binary.DynamicProtoMessage{ 1: guildId, 2: roleId, })) - _, err := s.c.sendAndWaitDynamic(seq, packet) + _, err := s.c.call(req) if err != nil { return errors.Wrap(err, "send packet error") } @@ -378,11 +374,11 @@ func (s *GuildService) SetUserRoleInGuild(guildId uint64, set bool, roleId uint6 } else { setOrRemove[3] = user } - seq, packet := s.c.uniPacket("OidbSvcTrpcTcp.0x101a_1", s.c.packOIDBPackageDynamically(4122, 1, binary.DynamicProtoMessage{ + req := s.c.uniRequest("OidbSvcTrpcTcp.0x101a_1", s.c.packOIDBPackageDynamically(4122, 1, binary.DynamicProtoMessage{ 1: guildId, 2: setOrRemove, })) - _, err := s.c.sendAndWaitDynamic(seq, packet) + _, err := s.c.call(req) if err != nil { return errors.Wrap(err, "send packet error") } @@ -391,7 +387,7 @@ func (s *GuildService) SetUserRoleInGuild(guildId uint64, set bool, roleId uint6 func (s *GuildService) ModifyRoleInGuild(guildId uint64, roleId uint64, name string, color uint32, indepedent bool) error { u1 := uint32(1) - seq, packet := s.c.uniPacket("OidbSvcTrpcTcp.0x100d_1", s.c.packOIDBPackageDynamically(4109, 1, binary.DynamicProtoMessage{ + req := s.c.uniRequest("OidbSvcTrpcTcp.0x100d_1", s.c.packOIDBPackageDynamically(4109, 1, binary.DynamicProtoMessage{ 1: guildId, 2: roleId, 3: binary.DynamicProtoMessage{ @@ -405,7 +401,7 @@ func (s *GuildService) ModifyRoleInGuild(guildId uint64, roleId uint64, name str 3: indepedent, }, })) - _, err := s.c.sendAndWaitDynamic(seq, packet) + _, err := s.c.call(req) if err != nil { return errors.Wrap(err, "send packet error") } @@ -428,13 +424,13 @@ func (s *GuildService) FetchGuestGuild(guildId uint64) (*GuildMeta, error) { 1: guildId, }, }) - seq, packet := s.c.uniPacket("OidbSvcTrpcTcp.0xf57_9", payload) - rsp, err := s.c.sendAndWaitDynamic(seq, packet) + req := s.c.uniRequest("OidbSvcTrpcTcp.0xf57_9", payload) + rsp, err := s.c.call(req) if err != nil { return nil, errors.Wrap(err, "send packet error") } body := new(channel.ChannelOidb0Xf57Rsp) - if err = unpackOIDBPackage(rsp, body); err != nil { + if err = unpackOIDBPackage(rsp.Body, body); err != nil { return nil, errors.Wrap(err, "decode packet error") } return &GuildMeta{ @@ -450,7 +446,7 @@ func (s *GuildService) FetchGuestGuild(guildId uint64) (*GuildMeta, error) { } func (s *GuildService) FetchChannelList(guildId uint64) (r []*ChannelInfo, e error) { - seq, packet := s.c.uniPacket("OidbSvcTrpcTcp.0xf5d_1", + req := s.c.uniRequest("OidbSvcTrpcTcp.0xf5d_1", s.c.packOIDBPackageDynamically(3933, 1, binary.DynamicProtoMessage{ 1: guildId, @@ -458,12 +454,12 @@ func (s *GuildService) FetchChannelList(guildId uint64) (r []*ChannelInfo, e err 1: uint32(1), }, })) - rsp, err := s.c.sendAndWaitDynamic(seq, packet) + rsp, err := s.c.call(req) if err != nil { return nil, errors.Wrap(err, "send packet error") } body := new(channel.ChannelOidb0Xf5DRsp) - if err = unpackOIDBPackage(rsp, body); err != nil { + if err = unpackOIDBPackage(rsp.Body, body); err != nil { return nil, errors.Wrap(err, "decode packet error") } for _, info := range body.Rsp.Channels { @@ -473,13 +469,13 @@ func (s *GuildService) FetchChannelList(guildId uint64) (r []*ChannelInfo, e err } func (s *GuildService) FetchChannelInfo(guildId, channelId uint64) (*ChannelInfo, error) { - seq, packet := s.c.uniPacket("OidbSvcTrpcTcp.0xf55_1", s.c.packOIDBPackageDynamically(3925, 1, binary.DynamicProtoMessage{1: guildId, 2: channelId})) - rsp, err := s.c.sendAndWaitDynamic(seq, packet) + req := s.c.uniRequest("OidbSvcTrpcTcp.0xf55_1", s.c.packOIDBPackageDynamically(3925, 1, binary.DynamicProtoMessage{1: guildId, 2: channelId})) + rsp, err := s.c.call(req) if err != nil { return nil, errors.Wrap(err, "send packet error") } body := new(channel.ChannelOidb0Xf55Rsp) - if err = unpackOIDBPackage(rsp, body); err != nil { + if err = unpackOIDBPackage(rsp.Body, body); err != nil { return nil, errors.Wrap(err, "decode packet error") } return convertChannelInfo(body.Info), nil @@ -527,14 +523,14 @@ func (s *GuildService) GetTopicChannelFeeds(guildId, channelId uint64) ([]*topic }, }, }) - seq, packet := s.c.uniPacket("QChannelSvr.trpc.qchannel.commreader.ComReader.GetChannelTimelineFeeds", payload) - rsp, err := s.c.sendAndWaitDynamic(seq, packet) + call := s.c.uniRequest("QChannelSvr.trpc.qchannel.commreader.ComReader.GetChannelTimelineFeeds", payload) + rsp, err := s.c.call(call) if err != nil { return nil, errors.New("send packet error") } pkg := new(qweb.QWebRsp) body := new(channel.StGetChannelFeedsRsp) - if err = proto.Unmarshal(rsp, pkg); err != nil { + if err = proto.Unmarshal(rsp.Body, pkg); err != nil { return nil, errors.Wrap(err, "failed to unmarshal protobuf message") } if err = proto.Unmarshal(pkg.BusiBuff, body); err != nil { @@ -597,14 +593,13 @@ func (s *GuildService) PostTopicChannelFeed(guildId, channelId uint64, feed *top }, }, }) - seq, packet := s.c.uniPacket("QChannelSvr.trpc.qchannel.commwriter.ComWriter.PublishFeed", payload) - rsp, err := s.c.sendAndWaitDynamic(seq, packet) + rsp, err := s.c.call(s.c.uniRequest("QChannelSvr.trpc.qchannel.commwriter.ComWriter.PublishFeed", payload)) if err != nil { return errors.New("send packet error") } pkg := new(qweb.QWebRsp) body := new(channel.StPublishFeedRsp) - if err = proto.Unmarshal(rsp, pkg); err != nil { + if err = proto.Unmarshal(rsp.Body, pkg); err != nil { return errors.Wrap(err, "failed to unmarshal protobuf message") } if err = proto.Unmarshal(pkg.BusiBuff, body); err != nil { @@ -618,7 +613,7 @@ func (s *GuildService) PostTopicChannelFeed(guildId, channelId uint64, feed *top func (s *GuildService) fetchMemberRoles(guildId uint64, tinyId uint64) ([]*GuildRole, error) { u1 := uint32(1) - seq, packet := s.c.uniPacket("OidbSvcTrpcTcp.0x1017_1", s.c.packOIDBPackageDynamically(4119, 1, binary.DynamicProtoMessage{ + req := s.c.uniRequest("OidbSvcTrpcTcp.0x1017_1", s.c.packOIDBPackageDynamically(4119, 1, binary.DynamicProtoMessage{ 1: guildId, 2: tinyId, 4: binary.DynamicProtoMessage{ @@ -627,12 +622,12 @@ func (s *GuildService) fetchMemberRoles(guildId uint64, tinyId uint64) ([]*Guild 3: u1, }, })) - rsp, err := s.c.sendAndWaitDynamic(seq, packet) + rsp, err := s.c.call(req) if err != nil { return nil, errors.Wrap(err, "send packet error") } body := new(channel.ChannelOidb0X1017Rsp) - if err = unpackOIDBPackage(rsp, body); err != nil { + if err = unpackOIDBPackage(rsp.Body, body); err != nil { return nil, errors.Wrap(err, "decode packet error") } p1 := body.GetP1() @@ -709,13 +704,13 @@ func convertChannelInfo(info *channel.GuildChannelInfo) *ChannelInfo { } func (c *QQClient) syncChannelFirstView() { - rsp, err := c.sendAndWaitDynamic(c.buildSyncChannelFirstViewPacket()) + rsp, err := c.call(c.buildSyncChannelFirstViewPacket()) if err != nil { c.Error("sync channel error: %v", err) return } firstViewRsp := new(channel.FirstViewRsp) - if err = proto.Unmarshal(rsp, firstViewRsp); err != nil { + if err = proto.Unmarshal(rsp.Body, firstViewRsp); err != nil { return } c.GuildService.TinyId = firstViewRsp.GetSelfTinyid() @@ -728,14 +723,14 @@ func (c *QQClient) syncChannelFirstView() { } } -func (c *QQClient) buildSyncChannelFirstViewPacket() (uint16, []byte) { +func (c *QQClient) buildSyncChannelFirstViewPacket() *network.Request { req := &channel.FirstViewReq{ LastMsgTime: proto.Uint64(0), Seq: proto.Uint32(0), DirectMessageFlag: proto.Uint32(1), } payload, _ := proto.Marshal(req) - return c.uniPacket("trpc.group_pro.synclogic.SyncLogic.SyncFirstView", payload) + return c.uniRequest("trpc.group_pro.synclogic.SyncLogic.SyncFirstView", payload) } func decodeGuildPushFirstView(c *QQClient, resp *network.Response) (interface{}, error) { diff --git a/client/guild_msg.go b/client/guild_msg.go index 65273c18..13b401ca 100644 --- a/client/guild_msg.go +++ b/client/guild_msg.go @@ -35,10 +35,6 @@ type guildImageUploadResponse struct { IsExists bool } -func init() { - decoders["ImgStore.QQMeetPicUp"] = decodeGuildImageStoreResponse -} - func (s *GuildService) SendGuildChannelMessage(guildId, channelId uint64, m *message.SendingMessage) (*message.GuildChannelMessage, error) { mr := rand.Uint32() // 客户端似乎是生成的 u32 虽然类型是u64 for _, elem := range m.Elements { @@ -68,13 +64,12 @@ func (s *GuildService) SendGuildChannelMessage(guildId, channelId uint64, m *mes }, }} payload, _ := proto.Marshal(req) - seq, packet := s.c.uniPacket("MsgProxy.SendMsg", payload) - rsp, err := s.c.sendAndWaitDynamic(seq, packet) + rsp, err := s.c.commandCall("MsgProxy.SendMsg", payload) if err != nil { return nil, errors.Wrap(err, "send packet error") } body := new(channel.DF62RspBody) - if err = proto.Unmarshal(rsp, body); err != nil { + if err = proto.Unmarshal(rsp.Body, body); err != nil { return nil, errors.Wrap(err, "failed to unmarshal protobuf message") } if body.GetResult() != 0 { @@ -99,7 +94,7 @@ func (s *GuildService) SendGuildChannelMessage(guildId, channelId uint64, m *mes } func (s *GuildService) QueryImage(guildId, channelId uint64, hash []byte, size uint64) (*message.GuildImageElement, error) { - rsp, err := s.c.sendAndWait(s.c.buildGuildImageStorePacket(guildId, channelId, hash, size)) + rsp, err := s.c.callAndDecode(s.c.buildGuildImageStorePacket(guildId, channelId, hash, size), decodeGuildImageStoreResponse) if err != nil { return nil, errors.Wrap(err, "send packet error") } @@ -122,7 +117,7 @@ func (s *GuildService) UploadGuildImage(guildId, channelId uint64, img io.ReadSe _, _ = img.Seek(0, io.SeekStart) // safe fh, length := utils.ComputeMd5AndLength(img) _, _ = img.Seek(0, io.SeekStart) - rsp, err := s.c.sendAndWait(s.c.buildGuildImageStorePacket(guildId, channelId, fh, uint64(length))) + rsp, err := s.c.callAndDecode(s.c.buildGuildImageStorePacket(guildId, channelId, fh, uint64(length)), decodeGuildImageStoreResponse) if err != nil { return nil, err } @@ -215,19 +210,18 @@ func (s *GuildService) pullChannelMessages(guildId, channelId, beginSeq, endSeq, WithVersionFlag: &withVersionFlag, DirectMessageFlag: &directFlag, }) - seq, packet := s.c.uniPacket("trpc.group_pro.synclogic.SyncLogic.GetChannelMsg", payload) - rsp, err := s.c.sendAndWaitDynamic(seq, packet) + rsp, err := s.c.commandCall("trpc.group_pro.synclogic.SyncLogic.GetChannelMsg", payload) if err != nil { return nil, errors.Wrap(err, "send packet error") } msgRsp := new(channel.ChannelMsgRsp) - if err = proto.Unmarshal(rsp, msgRsp); err != nil { + if err = proto.Unmarshal(rsp.Body, msgRsp); err != nil { return nil, errors.Wrap(err, "failed to unmarshal protobuf message") } return msgRsp.ChannelMsg.Msgs, nil } -func (c *QQClient) buildGuildImageStorePacket(guildId, channelId uint64, hash []byte, size uint64) (uint16, []byte) { +func (c *QQClient) buildGuildImageStorePacket(guildId, channelId uint64, hash []byte, size uint64) *network.Request { payload, _ := proto.Marshal(&cmd0x388.D388ReqBody{ NetType: proto.Uint32(3), Subcmd: proto.Uint32(1), @@ -252,7 +246,7 @@ func (c *QQClient) buildGuildImageStorePacket(guildId, channelId uint64, hash [] }, CommandId: proto.Uint32(83), }) - return c.uniPacket("ImgStore.QQMeetPicUp", payload) + return c.uniRequest("ImgStore.QQMeetPicUp", payload) } func decodeGuildMessageEmojiReactions(content *channel.ChannelMsgContent) (r []*message.GuildMessageEmojiReaction) { @@ -349,13 +343,13 @@ func (s *GuildService) parseGuildChannelMessage(msg *channel.ChannelMsgContent) } // PttCenterSvr.GroupShortVideoUpReq -func (c *QQClient) buildPttGuildVideoUpReq(videoHash, thumbHash []byte, guildId, channelId int64, videoSize, thumbSize int64) (uint16, []byte) { +func (c *QQClient) buildPttGuildVideoUpReq(videoHash, thumbHash []byte, guildId, channelId int64, videoSize, thumbSize int64) *network.Request { pb := c.buildPttGroupShortVideoProto(videoHash, thumbHash, guildId, videoSize, thumbSize, 4) pb.PttShortVideoUploadReq.BusinessType = 4601 pb.PttShortVideoUploadReq.ToUin = channelId pb.ExtensionReq[0].SubBusiType = 4601 payload, _ := proto.Marshal(pb) - return c.uniPacket("PttCenterSvr.GroupShortVideoUpReq", payload) + return c.uniRequest("PttCenterSvr.GroupShortVideoUpReq", payload) } func (c *QQClient) UploadGuildShortVideo(guildId, channelId uint64, video, thumb io.ReadSeeker) (*message.ShortVideoElement, error) { @@ -367,7 +361,7 @@ func (c *QQClient) UploadGuildShortVideo(guildId, channelId uint64, video, thumb pttWaiter.Wait(key) defer pttWaiter.Done(key) - i, err := c.sendAndWait(c.buildPttGuildVideoUpReq(videoHash, thumbHash, int64(guildId), int64(channelId), videoLen, thumbLen)) + i, err := c.callAndDecode(c.buildPttGuildVideoUpReq(videoHash, thumbHash, int64(guildId), int64(channelId), videoLen, thumbLen), decodeGroupShortVideoUploadResponse) if err != nil { return nil, errors.Wrap(err, "upload req error") } diff --git a/client/image.go b/client/image.go index 4570a800..ed825e52 100644 --- a/client/image.go +++ b/client/image.go @@ -23,12 +23,6 @@ import ( "github.com/Mrs4s/MiraiGo/utils" ) -func init() { - decoders["ImgStore.GroupPicUp"] = decodeGroupImageStoreResponse - decoders["ImgStore.GroupPicDown"] = decodeGroupImageDownloadResponse - decoders["OidbSvc.0xe07_0"] = decodeImageOcrResponse -} - var imgWaiter = utils.NewUploadWaiter() type imageUploadResponse struct { @@ -53,8 +47,8 @@ func (c *QQClient) UploadGroupImage(groupCode int64, img io.ReadSeeker) (*messag imgWaiter.Wait(key) defer imgWaiter.Done(key) - seq, pkt := c.buildGroupImageStorePacket(groupCode, fh, int32(length)) - r, err := c.sendAndWait(seq, pkt) + req := c.buildGroupImageStoreRequest(groupCode, fh, int32(length)) + r, err := c.callAndDecode(req, decodeGroupImageStoreResponse) if err != nil { return nil, err } @@ -105,8 +99,8 @@ func (c *QQClient) UploadGroupImageByFile(groupCode int64, path string) (*messag imgWaiter.Wait(key) defer imgWaiter.Done(key) - seq, pkt := c.buildGroupImageStorePacket(groupCode, fh, int32(length)) - r, err := c.sendAndWait(seq, pkt) + req := c.buildGroupImageStoreRequest(groupCode, fh, int32(length)) + r, err := c.callAndDecode(req, decodeGroupImageStoreResponse) if err != nil { return nil, err } @@ -151,7 +145,7 @@ func (c *QQClient) UploadPrivateImage(target int64, img io.ReadSeeker) (*message } func (c *QQClient) GetGroupImageDownloadUrl(fileId, groupCode int64, fileMd5 []byte) (string, error) { - i, err := c.sendAndWait(c.buildGroupImageDownloadPacket(fileId, groupCode, fileMd5)) + i, err := c.callAndDecode(c.buildGroupImageDownloadRequest(fileId, groupCode, fileMd5), decodeGroupImageDownloadResponse) if err != nil { return "", err } @@ -191,7 +185,8 @@ func (c *QQClient) ImageOcr(img interface{}) (*OcrResponse, error) { } _ = b.Close() } - rsp, err := c.sendAndWait(c.buildImageOcrRequestPacket(url, strings.ToUpper(hex.EncodeToString(e.Md5)), e.Size, e.Width, e.Height)) + call := c.buildImageOcrRequestPacket(url, strings.ToUpper(hex.EncodeToString(e.Md5)), e.Size, e.Width, e.Height) + rsp, err := c.callAndDecode(call, decodeImageOcrResponse) if err != nil { return nil, err } @@ -201,7 +196,7 @@ func (c *QQClient) ImageOcr(img interface{}) (*OcrResponse, error) { } func (c *QQClient) QueryGroupImage(groupCode int64, hash []byte, size int32) (*message.GroupImageElement, error) { - r, err := c.sendAndWait(c.buildGroupImageStorePacket(groupCode, hash, size)) + r, err := c.callAndDecode(c.buildGroupImageStoreRequest(groupCode, hash, size), decodeGroupImageStoreResponse) if err != nil { return nil, err } @@ -216,7 +211,7 @@ func (c *QQClient) QueryGroupImage(groupCode int64, hash []byte, size int32) (*m } func (c *QQClient) QueryFriendImage(target int64, hash []byte, size int32) (*message.FriendImageElement, error) { - i, err := c.sendAndWait(c.buildOffPicUpPacket(target, hash, size)) + i, err := c.callAndDecode(c.buildOffPicUpRequest(target, hash, size), decodeOffPicUpResponse) if err != nil { return nil, err } @@ -239,7 +234,7 @@ func (c *QQClient) QueryFriendImage(target int64, hash []byte, size int32) (*mes } // ImgStore.GroupPicUp -func (c *QQClient) buildGroupImageStorePacket(groupCode int64, md5 []byte, size int32) (uint16, []byte) { +func (c *QQClient) buildGroupImageStoreRequest(groupCode int64, md5 []byte, size int32) *network.Request { name := utils.RandomString(16) + ".gif" req := &cmd0x388.D388ReqBody{ NetType: proto.Uint32(3), @@ -264,10 +259,10 @@ func (c *QQClient) buildGroupImageStorePacket(groupCode int64, md5 []byte, size Extension: EmptyBytes, } payload, _ := proto.Marshal(req) - return c.uniPacket("ImgStore.GroupPicUp", payload) + return c.uniRequest("ImgStore.GroupPicUp", payload) } -func (c *QQClient) buildGroupImageDownloadPacket(fileId, groupCode int64, fileMd5 []byte) (uint16, []byte) { +func (c *QQClient) buildGroupImageDownloadRequest(fileId, groupCode int64, fileMd5 []byte) *network.Request { req := &cmd0x388.D388ReqBody{ NetType: proto.Uint32(3), Subcmd: proto.Uint32(2), @@ -288,7 +283,7 @@ func (c *QQClient) buildGroupImageDownloadPacket(fileId, groupCode int64, fileMd }, } payload, _ := proto.Marshal(req) - return c.uniPacket("ImgStore.GroupPicDown", payload) + return c.uniRequest("ImgStore.GroupPicDown", payload) } func (c *QQClient) uploadOcrImage(img io.Reader) (string, error) { @@ -318,7 +313,7 @@ func (c *QQClient) uploadOcrImage(img io.Reader) (string, error) { } // OidbSvc.0xe07_0 -func (c *QQClient) buildImageOcrRequestPacket(url, md5 string, size, weight, height int32) (uint16, []byte) { +func (c *QQClient) buildImageOcrRequestPacket(url, md5 string, size, weight, height int32) *network.Request { body := &oidb.DE07ReqBody{ Version: 1, Entrance: 3, @@ -334,7 +329,7 @@ func (c *QQClient) buildImageOcrRequestPacket(url, md5 string, size, weight, hei } b, _ := proto.Marshal(body) payload := c.packOIDBPackage(3591, 0, b) - return c.uniPacket("OidbSvc.0xe07_0", payload) + return c.uniRequest("OidbSvc.0xe07_0", payload) } // ImgStore.GroupPicUp diff --git a/client/internal/network/packet.go b/client/internal/network/rpc.go similarity index 65% rename from client/internal/network/packet.go rename to client/internal/network/rpc.go index 6e4146b7..81747087 100644 --- a/client/internal/network/packet.go +++ b/client/internal/network/rpc.go @@ -1,5 +1,15 @@ package network +// Call is a client-side RPC call. +// refer to `net/rpc` +type Call struct { + Request *Request + Response *Response + Err error + Params RequestParams + Done chan *Call +} + type RequestParams map[string]interface{} func (p RequestParams) Bool(k string) bool { diff --git a/client/multimsg.go b/client/multimsg.go index 8b7ab20d..5ee2d76c 100644 --- a/client/multimsg.go +++ b/client/multimsg.go @@ -17,13 +17,8 @@ import ( "github.com/Mrs4s/MiraiGo/utils" ) -func init() { - decoders["MultiMsg.ApplyUp"] = decodeMultiApplyUpResponse - decoders["MultiMsg.ApplyDown"] = decodeMultiApplyDownResponse -} - // MultiMsg.ApplyUp -func (c *QQClient) buildMultiApplyUpPacket(data, hash []byte, buType int32, groupUin int64) (uint16, []byte) { +func (c *QQClient) buildMultiApplyUpPacket(data, hash []byte, buType int32, groupUin int64) *network.Request { req := &multimsg.MultiReqBody{ Subcmd: 1, TermType: 5, @@ -41,7 +36,7 @@ func (c *QQClient) buildMultiApplyUpPacket(data, hash []byte, buType int32, grou BuType: buType, } payload, _ := proto.Marshal(req) - return c.uniPacket("MultiMsg.ApplyUp", payload) + return c.uniRequest("MultiMsg.ApplyUp", payload) } // MultiMsg.ApplyUp @@ -64,7 +59,7 @@ func decodeMultiApplyUpResponse(_ *QQClient, resp *network.Response) (interface{ } // MultiMsg.ApplyDown -func (c *QQClient) buildMultiApplyDownPacket(resID string) (uint16, []byte) { +func (c *QQClient) buildMultiApplyDownPacket(resID string) *network.Request { req := &multimsg.MultiReqBody{ Subcmd: 2, TermType: 5, @@ -81,7 +76,7 @@ func (c *QQClient) buildMultiApplyDownPacket(resID string) (uint16, []byte) { ReqChannelType: 2, } payload, _ := proto.Marshal(req) - return c.uniPacket("MultiMsg.ApplyDown", payload) + return c.uniRequest("MultiMsg.ApplyDown", payload) } // MultiMsg.ApplyDown @@ -182,7 +177,7 @@ func (c *QQClient) GetForwardMessage(resID string) *message.ForwardMessage { } func (c *QQClient) DownloadForwardMessage(resId string) *message.ForwardElement { - i, err := c.sendAndWait(c.buildMultiApplyDownPacket(resId)) + i, err := c.callAndDecode(c.buildMultiApplyDownPacket(resId), decodeMultiApplyDownResponse) if err != nil { return nil } diff --git a/client/network.go b/client/network.go index 992a9962..83b9d36f 100644 --- a/client/network.go +++ b/client/network.go @@ -146,6 +146,52 @@ func (c *QQClient) Disconnect() { c.TCP.Close() } +func (c *QQClient) send(call *network.Call) { + if call.Done == nil { + call.Done = make(chan *network.Call, 3) // use buffered channel + } + seq := uint16(call.Request.SequenceID) + c.pendingMu.Lock() + c.pending[seq] = call + c.pendingMu.Unlock() + + err := c.sendPacket(c.transport.PackPacket(call.Request)) + if err != nil { + c.pendingMu.Lock() + call = c.pending[seq] + delete(c.pending, seq) + call.Err = err + call.Done <- call + c.pendingMu.Unlock() + } +} + +func (c *QQClient) sendReq(req *network.Request) { + c.send(&network.Call{Request: req}) +} + +func (c *QQClient) call(req *network.Request) (*network.Response, error) { + call := &network.Call{ + Request: req, + Done: make(chan *network.Call, 3), + } + c.send(call) + select { + case <-call.Done: + return call.Response, call.Err + case <-time.After(time.Second * 15): + return nil, errors.New("Packet timed out") + } +} + +func (c *QQClient) callAndDecode(req *network.Request, decoder func(*QQClient, *network.Response) (interface{}, error)) (interface{}, error) { + resp, err := c.call(req) + if err != nil { + return nil, err + } + return decoder(c, resp) +} + func (c *QQClient) sendAndWait(seq uint16, pkt []byte) (interface{}, error) { return c.sendAndWaitParams(seq, pkt, nil) } @@ -325,6 +371,26 @@ func (c *QQClient) netLoop() { c.Dump("packet decode error: %v - %v", req.Body, req.CommandName, pan) } }() + + // snapshot of read call + c.pendingMu.Lock() + call := c.pending[uint16(req.SequenceID)] + if call != nil { + call.Response = &network.Response{ + SequenceID: req.SequenceID, + CommandName: req.CommandName, + Body: req.Body, + // Request: nil, + } + } + c.pendingMu.Unlock() + if call != nil { + select { + case call.Done <- call: + default: + } + } + if decoder, ok := decoders[req.CommandName]; ok { // found predefined decoder info, ok := c.handlers.LoadAndDelete(uint16(req.SequenceID)) diff --git a/client/offline_file.go b/client/offline_file.go index b06b4109..f5c9cdf0 100644 --- a/client/offline_file.go +++ b/client/offline_file.go @@ -8,11 +8,7 @@ import ( "github.com/Mrs4s/MiraiGo/internal/proto" ) -func init() { - decoders["OfflineFilleHandleSvr.pb_ftn_CMD_REQ_APPLY_DOWNLOAD-1200"] = decodeOfflineFileDownloadResponse -} - -func (c *QQClient) buildOfflineFileDownloadRequestPacket(uuid []byte) (uint16, []byte) { +func (c *QQClient) buildOfflineFileDownloadRequestPacket(uuid []byte) *network.Request { seq := c.nextSeq() req := &cmd0x346.C346ReqBody{ Cmd: 1200, @@ -29,8 +25,7 @@ func (c *QQClient) buildOfflineFileDownloadRequestPacket(uuid []byte) (uint16, [ }, } payload, _ := proto.Marshal(req) - packet := c.uniPacketWithSeq(seq, "OfflineFilleHandleSvr.pb_ftn_CMD_REQ_APPLY_DOWNLOAD-1200", payload) - return seq, packet + return c.uniPacketWithSeq(seq, "OfflineFilleHandleSvr.pb_ftn_CMD_REQ_APPLY_DOWNLOAD-1200", payload) } func decodeOfflineFileDownloadResponse(c *QQClient, resp *network.Response) (interface{}, error) { diff --git a/client/packet.go b/client/packet.go index ddf6e11a..d2a47ddb 100644 --- a/client/packet.go +++ b/client/packet.go @@ -17,7 +17,19 @@ func (c *QQClient) buildOicqRequestPacket(uin int64, command uint16, body []byte } //go:noinline -func (c *QQClient) uniPacket(command string, body []byte) (uint16, []byte) { +func (c *QQClient) uniRequest(command string, body []byte) *network.Request { + seq := c.nextSeq() + return &network.Request{ + Type: network.RequestTypeSimple, + EncryptType: network.EncryptTypeD2Key, + Uin: c.Uin, + SequenceID: int32(seq), + CommandName: command, + Body: body, + } +} + +func (c *QQClient) commandCall(command string, body []byte) (*network.Response, error) { seq := c.nextSeq() req := network.Request{ Type: network.RequestTypeSimple, @@ -27,11 +39,11 @@ func (c *QQClient) uniPacket(command string, body []byte) (uint16, []byte) { CommandName: command, Body: body, } - return seq, c.transport.PackPacket(&req) + return c.call(&req) } -//go:noinline -func (c *QQClient) uniPacketWithSeq(seq uint16, command string, body []byte) []byte { +func (c *QQClient) commandCallAndDecode(command string, body []byte, decode func(*QQClient, *network.Response) (interface{}, error)) (interface{}, error) { + seq := c.nextSeq() req := network.Request{ Type: network.RequestTypeSimple, EncryptType: network.EncryptTypeD2Key, @@ -40,5 +52,22 @@ func (c *QQClient) uniPacketWithSeq(seq uint16, command string, body []byte) []b CommandName: command, Body: body, } - return c.transport.PackPacket(&req) + resp, err := c.call(&req) + if err != nil { + return nil, err + } + return decode(c, resp) +} + +//go:noinline +func (c *QQClient) uniPacketWithSeq(seq uint16, command string, body []byte) *network.Request { + req := network.Request{ + Type: network.RequestTypeSimple, + EncryptType: network.EncryptTypeD2Key, + Uin: c.Uin, + SequenceID: int32(seq), + CommandName: command, + Body: body, + } + return &req } diff --git a/client/private_msg.go b/client/private_msg.go index ac118d66..6a4c4ceb 100644 --- a/client/private_msg.go +++ b/client/private_msg.go @@ -6,6 +6,7 @@ import ( "github.com/pkg/errors" + "github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/client/pb/msg" "github.com/Mrs4s/MiraiGo/internal/proto" "github.com/Mrs4s/MiraiGo/message" @@ -37,13 +38,13 @@ func (c *QQClient) SendPrivateMessage(target int64, m *message.SendingMessage) * if i == 0 { seq = fseq } - _, pkt := c.buildFriendSendingPacket(target, fseq, mr, int32(len(fragmented)), int32(i), div, t, elems) - _ = c.sendPacket(pkt) + req := c.buildFriendSendingPacket(target, fseq, mr, int32(len(fragmented)), int32(i), div, t, elems) + c.sendReq(req) } } else { seq = c.nextFriendSeq() - _, pkt := c.buildFriendSendingPacket(target, seq, mr, 1, 0, 0, t, m.Elements) - _ = c.sendPacket(pkt) + pkt := c.buildFriendSendingPacket(target, seq, mr, 1, 0, 0, t, m.Elements) + c.sendReq(pkt) } c.stat.MessageSent.Add(1) ret := &message.PrivateMessage{ @@ -82,8 +83,8 @@ func (c *QQClient) SendGroupTempMessage(groupCode, target int64, m *message.Send mr := int32(rand.Uint32()) seq := c.nextFriendSeq() t := time.Now().Unix() - _, pkt := c.buildGroupTempSendingPacket(group.Uin, target, seq, mr, t, m) - _ = c.sendPacket(pkt) + pkt := c.buildGroupTempSendingPacket(group.Uin, target, seq, mr, t, m) + c.sendReq(pkt) c.stat.MessageSent.Add(1) return &message.TempMessage{ Id: seq, @@ -103,8 +104,8 @@ func (c *QQClient) sendWPATempMessage(target int64, sig []byte, m *message.Sendi mr := int32(rand.Uint32()) seq := c.nextFriendSeq() t := time.Now().Unix() - _, pkt := c.buildWPATempSendingPacket(target, sig, seq, mr, t, m) - _ = c.sendPacket(pkt) + pkt := c.buildWPATempSendingPacket(target, sig, seq, mr, t, m) + c.sendReq(pkt) c.stat.MessageSent.Add(1) return &message.TempMessage{ Id: seq, @@ -130,7 +131,7 @@ func (s *TempSessionInfo) SendMessage(m *message.SendingMessage) (*message.TempM } /* this function is unused -func (c *QQClient) buildGetOneDayRoamMsgRequest(target, lastMsgTime, random int64, count uint32) (uint16, []byte) { +func (c *QQClient) buildGetOneDayRoamMsgRequest(target, lastMsgTime, random int64, count uint32) *network.Request { seq := c.nextSeq() req := &msg.PbGetOneDayRoamMsgReq{ PeerUin: proto.Uint64(uint64(target)), @@ -145,7 +146,7 @@ func (c *QQClient) buildGetOneDayRoamMsgRequest(target, lastMsgTime, random int6 */ // MessageSvc.PbSendMsg -func (c *QQClient) buildFriendSendingPacket(target int64, msgSeq, r, pkgNum, pkgIndex, pkgDiv int32, time int64, m []message.IMessageElement) (uint16, []byte) { +func (c *QQClient) buildFriendSendingPacket(target int64, msgSeq, r, pkgNum, pkgIndex, pkgDiv int32, time int64, m []message.IMessageElement) *network.Request { var ptt *msg.Ptt if len(m) > 0 { if p, ok := m[0].(*message.PrivateVoiceElement); ok { @@ -178,11 +179,11 @@ func (c *QQClient) buildFriendSendingPacket(target int64, msgSeq, r, pkgNum, pkg }(), } payload, _ := proto.Marshal(req) - return c.uniPacket("MessageSvc.PbSendMsg", payload) + return c.uniRequest("MessageSvc.PbSendMsg", payload) } // MessageSvc.PbSendMsg -func (c *QQClient) buildGroupTempSendingPacket(groupUin, target int64, msgSeq, r int32, time int64, m *message.SendingMessage) (uint16, []byte) { +func (c *QQClient) buildGroupTempSendingPacket(groupUin, target int64, msgSeq, r int32, time int64, m *message.SendingMessage) *network.Request { req := &msg.SendMessageRequest{ RoutingHead: &msg.RoutingHead{GrpTmp: &msg.GrpTmp{ GroupUin: &groupUin, @@ -210,10 +211,10 @@ func (c *QQClient) buildGroupTempSendingPacket(groupUin, target int64, msgSeq, r }(), } payload, _ := proto.Marshal(req) - return c.uniPacket("MessageSvc.PbSendMsg", payload) + return c.uniRequest("MessageSvc.PbSendMsg", payload) } -func (c *QQClient) buildWPATempSendingPacket(uin int64, sig []byte, msgSeq, r int32, time int64, m *message.SendingMessage) (uint16, []byte) { +func (c *QQClient) buildWPATempSendingPacket(uin int64, sig []byte, msgSeq, r int32, time int64, m *message.SendingMessage) *network.Request { req := &msg.SendMessageRequest{ RoutingHead: &msg.RoutingHead{WpaTmp: &msg.WPATmp{ ToUin: proto.Uint64(uint64(uin)), @@ -241,5 +242,5 @@ func (c *QQClient) buildWPATempSendingPacket(uin int64, sig []byte, msgSeq, r in }(), } payload, _ := proto.Marshal(req) - return c.uniPacket("MessageSvc.PbSendMsg", payload) + return c.uniRequest("MessageSvc.PbSendMsg", payload) } diff --git a/client/ptt.go b/client/ptt.go index ad871469..08f0481b 100644 --- a/client/ptt.go +++ b/client/ptt.go @@ -147,7 +147,8 @@ func (c *QQClient) UploadGroupShortVideo(groupCode int64, video, thumb io.ReadSe pttWaiter.Wait(key) defer pttWaiter.Done(key) - i, err := c.sendAndWait(c.buildPttGroupShortVideoUploadReqPacket(videoHash, thumbHash, groupCode, videoLen, thumbLen)) + i, err := c.callAndDecode(c.buildPttGroupShortVideoUploadReq(videoHash, thumbHash, groupCode, videoLen, thumbLen), + decodeGroupShortVideoUploadResponse) if err != nil { return nil, errors.Wrap(err, "upload req error") } @@ -210,7 +211,7 @@ func (c *QQClient) UploadGroupShortVideo(groupCode int64, video, thumb io.ReadSe } func (c *QQClient) GetShortVideoUrl(uuid, md5 []byte) string { - i, err := c.sendAndWait(c.buildPttShortVideoDownReqPacket(uuid, md5)) + i, err := c.callAndDecode(c.buildPttShortVideoDownReq(uuid, md5), decodePttShortVideoDownResponse) if err != nil { return "" } @@ -245,7 +246,7 @@ func (c *QQClient) buildGroupPttStoreBDHExt(groupCode int64, md5 []byte, size, c } // PttCenterSvr.ShortVideoDownReq -func (c *QQClient) buildPttShortVideoDownReqPacket(uuid, md5 []byte) (uint16, []byte) { +func (c *QQClient) buildPttShortVideoDownReq(uuid, md5 []byte) *network.Request { seq := c.nextSeq() body := &pttcenter.ShortVideoReqBody{ Cmd: 400, @@ -265,8 +266,7 @@ func (c *QQClient) buildPttShortVideoDownReqPacket(uuid, md5 []byte) (uint16, [] }, } payload, _ := proto.Marshal(body) - packet := c.uniPacketWithSeq(seq, "PttCenterSvr.ShortVideoDownReq", payload) - return seq, packet + return c.uniPacketWithSeq(seq, "PttCenterSvr.ShortVideoDownReq", payload) } func (c *QQClient) buildPttGroupShortVideoProto(videoHash, thumbHash []byte, toUin, videoSize, thumbSize int64, chattype int32) *pttcenter.ShortVideoReqBody { @@ -303,9 +303,9 @@ func (c *QQClient) buildPttGroupShortVideoProto(videoHash, thumbHash []byte, toU } // PttCenterSvr.GroupShortVideoUpReq -func (c *QQClient) buildPttGroupShortVideoUploadReqPacket(videoHash, thumbHash []byte, toUin, videoSize, thumbSize int64) (uint16, []byte) { +func (c *QQClient) buildPttGroupShortVideoUploadReq(videoHash, thumbHash []byte, toUin, videoSize, thumbSize int64) *network.Request { payload, _ := proto.Marshal(c.buildPttGroupShortVideoProto(videoHash, thumbHash, toUin, videoSize, thumbSize, 1)) - return c.uniPacket("PttCenterSvr.GroupShortVideoUpReq", payload) + return c.uniRequest("PttCenterSvr.GroupShortVideoUpReq", payload) } // PttCenterSvr.pb_pttCenter_CMD_REQ_APPLY_UPLOAD-500 diff --git a/client/qidian.go b/client/qidian.go index f2d17b33..73c83894 100644 --- a/client/qidian.go +++ b/client/qidian.go @@ -63,7 +63,7 @@ func (c *QQClient) getQiDianAddressDetailList() ([]*FriendInfo, error) { return ret, nil } -func (c *QQClient) buildLoginExtraPacket() (uint16, []byte) { +func (c *QQClient) buildLoginExtraPacket() *network.Request { req := &cmd0x3f6.C3F6ReqBody{ SubCmd: proto.Uint32(69), CrmCommonHead: &cmd0x3f6.C3F6CRMMsgHead{ @@ -86,10 +86,10 @@ func (c *QQClient) buildLoginExtraPacket() (uint16, []byte) { }, } payload, _ := proto.Marshal(req) - return c.uniPacket("qidianservice.69", payload) + return c.uniRequest("qidianservice.69", payload) } -func (c *QQClient) buildConnKeyRequestPacket() (uint16, []byte) { +func (c *QQClient) buildConnKeyRequestPacket() *network.Request { req := &cmd0x6ff.C501ReqBody{ ReqBody: &cmd0x6ff.SubCmd0X501ReqBody{ Uin: proto.Uint64(uint64(c.Uin)), @@ -101,7 +101,7 @@ func (c *QQClient) buildConnKeyRequestPacket() (uint16, []byte) { }, } payload, _ := proto.Marshal(req) - return c.uniPacket("HttpConn.0x6ff_501", payload) + return c.uniRequest("HttpConn.0x6ff_501", payload) } func (c *QQClient) bigDataRequest(subCmd uint32, req proto.Message) ([]byte, error) { diff --git a/client/recall.go b/client/recall.go index f1ed99e0..f050d318 100644 --- a/client/recall.go +++ b/client/recall.go @@ -22,7 +22,7 @@ func (c *QQClient) RecallGroupMessage(groupCode int64, msgID, msgInternalId int3 } } } - _, err := c.sendAndWait(c.buildGroupRecallPacket(groupCode, msgID, msgInternalId)) + _, err := c.callAndDecode(c.buildGroupRecallPacket(groupCode, msgID, msgInternalId), decodeMsgWithDrawResponse) return err } @@ -30,7 +30,7 @@ func (c *QQClient) internalGroupRecall(groupCode int64, msgInternalID int32, m [ for _, item := range m { if item.InternalId == msgInternalID { flag = true - if _, err := c.sendAndWait(c.buildGroupRecallPacket(groupCode, item.Id, item.InternalId)); err != nil { + if _, err := c.callAndDecode(c.buildGroupRecallPacket(groupCode, item.Id, item.InternalId), decodeMsgWithDrawResponse); err != nil { return false, err } } @@ -39,12 +39,12 @@ func (c *QQClient) internalGroupRecall(groupCode int64, msgInternalID int32, m [ } func (c *QQClient) RecallPrivateMessage(uin, ts int64, msgID, msgInternalId int32) error { - _, err := c.sendAndWait(c.buildPrivateRecallPacket(uin, ts, msgID, msgInternalId)) + _, err := c.callAndDecode(c.buildPrivateRecallPacket(uin, ts, msgID, msgInternalId), decodeMsgWithDrawResponse) return err } // PbMessageSvc.PbMsgWithDraw -func (c *QQClient) buildGroupRecallPacket(groupCode int64, msgSeq, msgRan int32) (uint16, []byte) { +func (c *QQClient) buildGroupRecallPacket(groupCode int64, msgSeq, msgRan int32) *network.Request { req := &msg.MsgWithDrawReq{ GroupWithDraw: []*msg.GroupMsgWithDrawReq{ { @@ -62,10 +62,10 @@ func (c *QQClient) buildGroupRecallPacket(groupCode int64, msgSeq, msgRan int32) }, } payload, _ := proto.Marshal(req) - return c.uniPacket("PbMessageSvc.PbMsgWithDraw", payload) + return c.uniRequest("PbMessageSvc.PbMsgWithDraw", payload) } -func (c *QQClient) buildPrivateRecallPacket(uin, ts int64, msgSeq, random int32) (uint16, []byte) { +func (c *QQClient) buildPrivateRecallPacket(uin, ts int64, msgSeq, random int32) *network.Request { req := &msg.MsgWithDrawReq{C2CWithDraw: []*msg.C2CMsgWithDrawReq{ { MsgInfo: []*msg.C2CMsgInfo{ @@ -89,7 +89,7 @@ func (c *QQClient) buildPrivateRecallPacket(uin, ts int64, msgSeq, random int32) }, }} payload, _ := proto.Marshal(req) - return c.uniPacket("PbMessageSvc.PbMsgWithDraw", payload) + return c.uniRequest("PbMessageSvc.PbMsgWithDraw", payload) } func decodeMsgWithDrawResponse(_ *QQClient, resp *network.Response) (interface{}, error) { diff --git a/client/richmsg.go b/client/richmsg.go index efa3ba69..e7e464c6 100644 --- a/client/richmsg.go +++ b/client/richmsg.go @@ -6,6 +6,7 @@ import ( "github.com/pkg/errors" + "github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/client/pb/oidb" "github.com/Mrs4s/MiraiGo/internal/proto" "github.com/Mrs4s/MiraiGo/message" @@ -76,7 +77,7 @@ func (c *QQClient) SendGroupMusicShare(target int64, msg *message.MusicShareElem } }) defer c.onGroupMessageReceipt(eid) - _, _ = c.sendAndWait(c.buildRichMsgSendingPacket(0, target, msg, 1)) // rsp is empty chunk + _, _ = c.call(c.buildRichMsgSendingPacket(0, target, msg, 1)) // rsp is empty chunk select { case ret := <-ch: return ret, nil @@ -87,17 +88,17 @@ func (c *QQClient) SendGroupMusicShare(target int64, msg *message.MusicShareElem // SendFriendMusicShare 发送好友音乐卡片 func (c *QQClient) SendFriendMusicShare(target int64, msg *message.MusicShareElement) { - _, _ = c.sendAndWait(c.buildRichMsgSendingPacket(0, target, msg, 0)) + _, _ = c.call(c.buildRichMsgSendingPacket(0, target, msg, 0)) } // SendGuildMusicShare 发送频道音乐卡片 func (c *QQClient) SendGuildMusicShare(guildID, channelID uint64, msg *message.MusicShareElement) { // todo(wdvxdr): message receipt? - _, _ = c.sendAndWait(c.buildRichMsgSendingPacket(guildID, int64(channelID), msg, 3)) + _, _ = c.call(c.buildRichMsgSendingPacket(guildID, int64(channelID), msg, 3)) } // OidbSvc.0xb77_9 -func (c *QQClient) buildRichMsgSendingPacket(guild uint64, target int64, msg *message.MusicShareElement, sendType uint32) (uint16, []byte) { +func (c *QQClient) buildRichMsgSendingPacket(guild uint64, target int64, msg *message.MusicShareElement, sendType uint32) *network.Request { tp := musicType[msg.MusicType] // MusicType msgStyle := uint32(0) if msg.MusicUrl != "" { @@ -128,5 +129,5 @@ func (c *QQClient) buildRichMsgSendingPacket(guild uint64, target int64, msg *me } b, _ := proto.Marshal(body) payload := c.packOIDBPackage(2935, 9, b) - return c.uniPacket("OidbSvc.0xb77_9", payload) + return c.uniRequest("OidbSvc.0xb77_9", payload) } diff --git a/client/security.go b/client/security.go index daf51f19..614970e1 100644 --- a/client/security.go +++ b/client/security.go @@ -8,10 +8,6 @@ import ( "github.com/Mrs4s/MiraiGo/internal/proto" ) -func init() { - decoders["OidbSvc.0xbcb_0"] = decodeUrlCheckResponse -} - type UrlSecurityLevel int const ( @@ -22,14 +18,14 @@ const ( // CheckUrlSafely 通过TX服务器检查URL安全性 func (c *QQClient) CheckUrlSafely(url string) UrlSecurityLevel { - i, err := c.sendAndWait(c.buildUrlCheckRequest(url)) + i, err := c.callAndDecode(c.buildUrlCheckRequest(url), decodeUrlCheckResponse) if err != nil { return Unknown } return i.(UrlSecurityLevel) } -func (c *QQClient) buildUrlCheckRequest(url string) (uint16, []byte) { +func (c *QQClient) buildUrlCheckRequest(url string) *network.Request { payload := c.packOIDBPackageProto(3019, 0, &oidb.DBCBReqBody{ CheckUrlReq: &oidb.CheckUrlReq{ Url: []string{url}, @@ -45,7 +41,7 @@ func (c *QQClient) buildUrlCheckRequest(url string) (uint16, []byte) { Qua: proto.String("AQQ_2013 4.6/2013 8.4.184945&NA_0/000000&ADR&null18&linux&2017&C2293D02BEE31158&7.1.2&V3"), }, }) - return c.uniPacket("OidbSvc.0xbcb_0", payload) + return c.uniRequest("OidbSvc.0xbcb_0", payload) } func decodeUrlCheckResponse(_ *QQClient, resp *network.Response) (interface{}, error) { diff --git a/client/sync.go b/client/sync.go index eb5c463d..795d091d 100644 --- a/client/sync.go +++ b/client/sync.go @@ -17,16 +17,9 @@ import ( ) func init() { - decoders["StatSvc.GetDevLoginInfo"] = decodeDevListResponse decoders["StatSvc.SvcReqMSFLoginNotify"] = decodeLoginNotifyPacket - decoders["RegPrxySvc.getOffMsg"] = ignoreDecoder - decoders["RegPrxySvc.GetMsgV2"] = ignoreDecoder - decoders["RegPrxySvc.PbGetMsg"] = ignoreDecoder - decoders["RegPrxySvc.NoticeEnd"] = ignoreDecoder decoders["RegPrxySvc.PushParam"] = decodePushParamPacket decoders["RegPrxySvc.PbSyncMsg"] = decodeMsgSyncResponse - decoders["PbMessageSvc.PbMsgReadedReport"] = decodeMsgReadedResponse - decoders["MessageSvc.PushReaded"] = ignoreDecoder decoders["OnlinePush.PbC2CMsgSync"] = decodeC2CSyncPacket } @@ -52,7 +45,7 @@ type ( // GetAllowedClients 获取已允许的其他客户端 func (c *QQClient) GetAllowedClients() ([]*OtherClientInfo, error) { - i, err := c.sendAndWait(c.buildDeviceListRequestPacket()) + i, err := c.callAndDecode(c.buildDeviceListRequestPacket(), decodeDevListResponse) if err != nil { return nil, err } @@ -70,7 +63,7 @@ func (c *QQClient) GetAllowedClients() ([]*OtherClientInfo, error) { // RefreshStatus 刷新客户端状态 func (c *QQClient) RefreshStatus() error { - _, err := c.sendAndWait(c.buildGetOfflineMsgRequestPacket()) + _, err := c.call(c.buildGetOfflineMsgRequestPacket()) return err } @@ -95,8 +88,8 @@ func (c *QQClient) SyncSessions() (*SessionSyncResponse, error) { notifyChan <- true } }) - _, pkt := c.buildSyncMsgRequestPacket() - if err := c.sendPacket(pkt); err != nil { + pkt := c.buildSyncMsgRequestPacket() + if _, err := c.call(pkt); err != nil { stop() return nil, err } @@ -111,15 +104,15 @@ func (c *QQClient) SyncSessions() (*SessionSyncResponse, error) { // MarkGroupMessageReaded 标记群消息已读, 适当调用应该能减少风控 func (c *QQClient) MarkGroupMessageReaded(groupCode, seq int64) { - _, _ = c.sendAndWait(c.buildGroupMsgReadedPacket(groupCode, seq)) + _, _ = c.callAndDecode(c.buildGroupMsgReadedPacket(groupCode, seq), decodeMsgReadedResponse) } func (c *QQClient) MarkPrivateMessageReaded(uin, time int64) { - _, _ = c.sendAndWait(c.buildPrivateMsgReadedPacket(uin, time)) + _, _ = c.callAndDecode(c.buildPrivateMsgReadedPacket(uin, time), decodeMsgReadedResponse) } // StatSvc.GetDevLoginInfo -func (c *QQClient) buildDeviceListRequestPacket() (uint16, []byte) { +func (c *QQClient) buildDeviceListRequestPacket() *network.Request { req := &jce.SvcReqGetDevLoginInfo{ Guid: c.deviceInfo.Guid, LoginType: 1, @@ -136,11 +129,11 @@ func (c *QQClient) buildDeviceListRequestPacket() (uint16, []byte) { Context: make(map[string]string), Status: make(map[string]string), } - return c.uniPacket("StatSvc.GetDevLoginInfo", pkt.ToBytes()) + return c.uniRequest("StatSvc.GetDevLoginInfo", pkt.ToBytes()) } // RegPrxySvc.getOffMsg -func (c *QQClient) buildGetOfflineMsgRequestPacket() (uint16, []byte) { +func (c *QQClient) buildGetOfflineMsgRequestPacket() *network.Request { regReq := &jce.SvcReqRegisterNew{ RequestOptional: 0x101C2 | 32, C2CMsg: &jce.SvcReqGetMsgV2{ @@ -190,11 +183,11 @@ func (c *QQClient) buildGetOfflineMsgRequestPacket() (uint16, []byte) { Context: make(map[string]string), Status: make(map[string]string), } - return c.uniPacket("RegPrxySvc.getOffMsg", pkt.ToBytes()) + return c.uniRequest("RegPrxySvc.getOffMsg", pkt.ToBytes()) } // RegPrxySvc.PbSyncMsg -func (c *QQClient) buildSyncMsgRequestPacket() (uint16, []byte) { +func (c *QQClient) buildSyncMsgRequestPacket() *network.Request { oidbReq, _ := proto.Marshal(&oidb.D769RspBody{ ConfigList: []*oidb.D769ConfigSeq{ { @@ -262,26 +255,26 @@ func (c *QQClient) buildSyncMsgRequestPacket() (uint16, []byte) { Context: make(map[string]string), Status: make(map[string]string), } - return c.uniPacket("RegPrxySvc.infoSync", pkt.ToBytes()) + return c.uniRequest("RegPrxySvc.infoSync", pkt.ToBytes()) } // PbMessageSvc.PbMsgReadedReport -func (c *QQClient) buildGroupMsgReadedPacket(groupCode, msgSeq int64) (uint16, []byte) { +func (c *QQClient) buildGroupMsgReadedPacket(groupCode, msgSeq int64) *network.Request { req, _ := proto.Marshal(&msg.PbMsgReadedReportReq{GrpReadReport: []*msg.PbGroupReadedReportReq{{ GroupCode: proto.Uint64(uint64(groupCode)), LastReadSeq: proto.Uint64(uint64(msgSeq)), }}}) - return c.uniPacket("PbMessageSvc.PbMsgReadedReport", req) + return c.uniRequest("PbMessageSvc.PbMsgReadedReport", req) } -func (c *QQClient) buildPrivateMsgReadedPacket(uin, time int64) (uint16, []byte) { +func (c *QQClient) buildPrivateMsgReadedPacket(uin, time int64) *network.Request { req, _ := proto.Marshal(&msg.PbMsgReadedReportReq{C2CReadReport: &msg.PbC2CReadedReportReq{PairInfo: []*msg.UinPairReadInfo{ { PeerUin: proto.Uint64(uint64(uin)), LastReadTime: proto.Uint32(uint32(time)), }, }, SyncCookie: c.sig.SyncCookie}}) - return c.uniPacket("PbMessageSvc.PbMsgReadedReport", req) + return c.uniRequest("PbMessageSvc.PbMsgReadedReport", req) } // StatSvc.GetDevLoginInfo diff --git a/client/system_msg.go b/client/system_msg.go index 63ffeab8..6b545426 100644 --- a/client/system_msg.go +++ b/client/system_msg.go @@ -44,12 +44,12 @@ type ( ) func (c *QQClient) GetGroupSystemMessages() (*GroupSystemMessages, error) { - i, err := c.sendAndWait(c.buildSystemMsgNewGroupPacket(false)) + i, err := c.callAndDecode(c.buildSystemMsgNewGroupPacket(false), decodeSystemMsgGroupPacket) if err != nil { return nil, err } msg := i.(*GroupSystemMessages) - i, err = c.sendAndWait(c.buildSystemMsgNewGroupPacket(true)) + i, err = c.callAndDecode(c.buildSystemMsgNewGroupPacket(true), decodeSystemMsgGroupPacket) if err != nil { return nil, err } @@ -98,7 +98,7 @@ func (c *QQClient) exceptAndDispatchGroupSysMsg() { } // ProfileService.Pb.ReqSystemMsgNew.Group -func (c *QQClient) buildSystemMsgNewGroupPacket(suspicious bool) (uint16, []byte) { +func (c *QQClient) buildSystemMsgNewGroupPacket(suspicious bool) *network.Request { req := &structmsg.ReqSystemMsgNew{ MsgNum: 100, Version: 1000, @@ -130,11 +130,11 @@ func (c *QQClient) buildSystemMsgNewGroupPacket(suspicious bool) (uint16, []byte }(), } payload, _ := proto.Marshal(req) - return c.uniPacket("ProfileService.Pb.ReqSystemMsgNew.Group", payload) + return c.uniRequest("ProfileService.Pb.ReqSystemMsgNew.Group", payload) } // ProfileService.Pb.ReqSystemMsgAction.Group -func (c *QQClient) buildSystemMsgGroupActionPacket(reqID, requester, group int64, msgType int32, isInvite, accept, block bool, reason string) (uint16, []byte) { +func (c *QQClient) buildSystemMsgGroupActionPacket(reqID, requester, group int64, msgType int32, isInvite, accept, block bool, reason string) *network.Request { subSrcId := int32(31) groupMsgType := int32(1) if isInvite { @@ -163,11 +163,11 @@ func (c *QQClient) buildSystemMsgGroupActionPacket(reqID, requester, group int64 Language: 1000, } payload, _ := proto.Marshal(req) - return c.uniPacket("ProfileService.Pb.ReqSystemMsgAction.Group", payload) + return c.uniRequest("ProfileService.Pb.ReqSystemMsgAction.Group", payload) } // ProfileService.Pb.ReqSystemMsgAction.Friend -func (c *QQClient) buildSystemMsgFriendActionPacket(reqID, requester int64, accept bool) (uint16, []byte) { +func (c *QQClient) buildSystemMsgFriendActionPacket(reqID, requester int64, accept bool) *network.Request { infoType := int32(3) if accept { infoType = 2 @@ -186,7 +186,7 @@ func (c *QQClient) buildSystemMsgFriendActionPacket(reqID, requester int64, acce }, } payload, _ := proto.Marshal(req) - return c.uniPacket("ProfileService.Pb.ReqSystemMsgAction.Friend", payload) + return c.uniRequest("ProfileService.Pb.ReqSystemMsgAction.Friend", payload) } // ProfileService.Pb.ReqSystemMsgNew.Group diff --git a/client/translate.go b/client/translate.go index 6f0a65b1..9d1b5470 100644 --- a/client/translate.go +++ b/client/translate.go @@ -8,7 +8,7 @@ import ( "github.com/Mrs4s/MiraiGo/internal/proto" ) -func (c *QQClient) buildTranslatePacket(src, dst, text string) (uint16, []byte) { +func (c *QQClient) buildTranslatePacket(src, dst, text string) *network.Request { body := &oidb.TranslateReqBody{ BatchTranslateReq: &oidb.BatchTranslateReq{ SrcLanguage: src, @@ -23,11 +23,11 @@ func (c *QQClient) buildTranslatePacket(src, dst, text string) (uint16, []byte) Bodybuffer: b, } payload, _ := proto.Marshal(req) - return c.uniPacket("OidbSvc.0x990", payload) + return c.uniRequest("OidbSvc.0x990", payload) } func (c *QQClient) Translate(src, dst, text string) (string, error) { - rsp, err := c.sendAndWait(c.buildTranslatePacket(src, dst, text)) + rsp, err := c.callAndDecode(c.buildTranslatePacket(src, dst, text), decodeTranslateResponse) if err != nil { return "", err } diff --git a/client/web.go b/client/web.go index 47b13f7c..1c5c2852 100644 --- a/client/web.go +++ b/client/web.go @@ -90,12 +90,12 @@ func (c *QQClient) webSsoRequest(host, webCmd, data string) (string, error) { Type: proto.Uint32(0), Data: &data, }) - rspData, err := c.sendAndWaitDynamic(c.uniPacket(cmd, req)) + rspData, err := c.call(c.uniRequest(cmd, req)) if err != nil { return "", errors.Wrap(err, "send web sso request error") } rsp := &web.WebSsoResponseBody{} - if err = proto.Unmarshal(rspData, rsp); err != nil { + if err = proto.Unmarshal(rspData.Body, rsp); err != nil { return "", errors.Wrap(err, "unmarshal response error") } return rsp.GetData(), nil