From 63027b5a66e818e00c0a5a24e04042eae664552a Mon Sep 17 00:00:00 2001 From: wdvxdr Date: Tue, 2 Mar 2021 16:38:55 +0800 Subject: [PATCH] fix private ptt --- client/client.go | 49 +++++++++++++-------------- client/ptt.go | 88 ++++++++++++++++++++---------------------------- 2 files changed, 60 insertions(+), 77 deletions(-) diff --git a/client/client.go b/client/client.go index 9f770fd9..4d49142d 100644 --- a/client/client.go +++ b/client/client.go @@ -122,31 +122,30 @@ type loginSigInfo struct { } var decoders = map[string]func(*QQClient, uint16, []byte) (interface{}, error){ - "wtlogin.login": decodeLoginResponse, - "wtlogin.exchange_emp": decodeExchangeEmpResponse, - "StatSvc.register": decodeClientRegisterResponse, - "StatSvc.ReqMSFOffline": decodeMSFOfflinePacket, - "MessageSvc.PushNotify": decodeSvcNotify, - "OnlinePush.ReqPush": decodeOnlinePushReqPacket, - "OnlinePush.PbPushTransMsg": decodeOnlinePushTransPacket, - "ConfigPushSvc.PushReq": decodePushReqPacket, - "MessageSvc.PbGetMsg": decodeMessageSvcPacket, - "MessageSvc.PushForceOffline": decodeForceOfflinePacket, - "PbMessageSvc.PbMsgWithDraw": decodeMsgWithDrawResponse, - "friendlist.getFriendGroupList": decodeFriendGroupListResponse, - "friendlist.GetTroopListReqV2": decodeGroupListResponse, - "friendlist.GetTroopMemberListReq": decodeGroupMemberListResponse, - "group_member_card.get_group_member_card_info": decodeGroupMemberInfoResponse, - "PttStore.GroupPttUp": decodeGroupPttStoreResponse, - "LongConn.OffPicUp": decodeOffPicUpResponse, - "ProfileService.Pb.ReqSystemMsgNew.Group": decodeSystemMsgGroupPacket, - "ProfileService.Pb.ReqSystemMsgNew.Friend": decodeSystemMsgFriendPacket, - "OidbSvc.0xe07_0": decodeImageOcrResponse, - "OidbSvc.0xd79": decodeWordSegmentation, - "OidbSvc.0x990": decodeTranslateResponse, - "SummaryCard.ReqSummaryCard": decodeSummaryCardResponse, - "LightAppSvc.mini_app_info.GetAppInfoById": decodeAppInfoResponse, - "PttCenterSvr.pb_pttCenter_CMD_REQ_APPLY_UPLOAD-500": decodePrivatePttStoreResponse, + "wtlogin.login": decodeLoginResponse, + "wtlogin.exchange_emp": decodeExchangeEmpResponse, + "StatSvc.register": decodeClientRegisterResponse, + "StatSvc.ReqMSFOffline": decodeMSFOfflinePacket, + "MessageSvc.PushNotify": decodeSvcNotify, + "OnlinePush.ReqPush": decodeOnlinePushReqPacket, + "OnlinePush.PbPushTransMsg": decodeOnlinePushTransPacket, + "ConfigPushSvc.PushReq": decodePushReqPacket, + "MessageSvc.PbGetMsg": decodeMessageSvcPacket, + "MessageSvc.PushForceOffline": decodeForceOfflinePacket, + "PbMessageSvc.PbMsgWithDraw": decodeMsgWithDrawResponse, + "friendlist.getFriendGroupList": decodeFriendGroupListResponse, + "friendlist.GetTroopListReqV2": decodeGroupListResponse, + "friendlist.GetTroopMemberListReq": decodeGroupMemberListResponse, + "group_member_card.get_group_member_card_info": decodeGroupMemberInfoResponse, + "PttStore.GroupPttUp": decodeGroupPttStoreResponse, + "LongConn.OffPicUp": decodeOffPicUpResponse, + "ProfileService.Pb.ReqSystemMsgNew.Group": decodeSystemMsgGroupPacket, + "ProfileService.Pb.ReqSystemMsgNew.Friend": decodeSystemMsgFriendPacket, + "OidbSvc.0xe07_0": decodeImageOcrResponse, + "OidbSvc.0xd79": decodeWordSegmentation, + "OidbSvc.0x990": decodeTranslateResponse, + "SummaryCard.ReqSummaryCard": decodeSummaryCardResponse, + "LightAppSvc.mini_app_info.GetAppInfoById": decodeAppInfoResponse, } func init() { diff --git a/client/ptt.go b/client/ptt.go index ca2fc950..6c73f337 100644 --- a/client/ptt.go +++ b/client/ptt.go @@ -1,6 +1,7 @@ package client import ( + "bytes" "crypto/md5" "encoding/hex" "io" @@ -60,33 +61,31 @@ func (c *QQClient) UploadGroupPtt(groupCode int64, voice io.ReadSeeker) (*messag // UploadPrivatePtt 将语音数据使用好友语音通道上传到服务器, 返回 message.PrivateVoiceElement 可直接发送 func (c *QQClient) UploadPrivatePtt(target int64, voice []byte) (*message.PrivateVoiceElement, error) { h := md5.Sum(voice) - i, err := c.sendAndWait(c.buildPrivatePttStorePacket(target, h[:], int32(len(voice)), int32(len(voice)))) + ext := c.buildC2CPttStoreBDHExt(target, h[:], int32(len(voice)), int32(len(voice))) + rsp, err := c.highwayUploadByBDH(bytes.NewReader(voice), 26, c.highwaySession.SigSession, ext, false) if err != nil { return nil, err } - rsp := i.(pttUploadResponse) - if rsp.IsExists { - goto ok + if len(rsp) == 0 { + return nil, errors.New("miss rsp") } - for i, ip := range rsp.UploadIp { - err := c.uploadPtt(ip, rsp.UploadPort[i], rsp.UploadKey, rsp.FileKey, voice, h[:]) - if err != nil { - continue - } - goto ok + pkt := cmd0x346.C346RspBody{} + if err = proto.Unmarshal(rsp, &pkt); err != nil { + return nil, errors.Wrap(err, "failed to unmarshal protobuf message") + } + if pkt.ApplyUploadRsp == nil { + return nil, errors.New("miss apply upload rsp") } - return nil, errors.New("upload failed") -ok: return &message.PrivateVoiceElement{ Ptt: &msg.Ptt{ - FileType: proto.Int32(4), - SrcUin: &c.Uin, - FileMd5: h[:], - FileName: proto.String(hex.EncodeToString(h[:]) + ".amr"), - FileSize: proto.Int32(int32(len(voice))), - FileKey: rsp.FileKey, + FileType: proto.Int32(4), + SrcUin: &c.Uin, + FileUuid: pkt.ApplyUploadRsp.Uuid, + FileMd5: h[:], + FileName: proto.String(hex.EncodeToString(h[:]) + ".amr"), + FileSize: proto.Int32(int32(len(voice))), + // Reserve: constructPTTExtraInfo(1, int32(len(voice))), // todo length BoolValid: proto.Bool(true), - PbReserve: []byte{8, 0, 40, 0, 56, 0}, }}, nil } @@ -291,7 +290,7 @@ func decodeGroupPttStoreResponse(_ *QQClient, _ uint16, payload []byte) (interfa } // PttCenterSvr.pb_pttCenter_CMD_REQ_APPLY_UPLOAD-500 -func (c *QQClient) buildPrivatePttStorePacket(target int64, md5 []byte, size, voiceLength int32) (uint16, []byte) { +func (c *QQClient) buildC2CPttStoreBDHExt(target int64, md5 []byte, size, voiceLength int32) []byte { seq := c.nextSeq() req := &cmd0x346.C346ReqBody{ Cmd: 500, @@ -315,38 +314,7 @@ func (c *QQClient) buildPrivatePttStorePacket(target int64, md5 []byte, size, vo }, } payload, _ := proto.Marshal(req) - packet := packets.BuildUniPacket(c.Uin, seq, "PttCenterSvr.pb_pttCenter_CMD_REQ_APPLY_UPLOAD-500", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) - return seq, packet -} - -// PttCenterSvr.pb_pttCenter_CMD_REQ_APPLY_UPLOAD-500 -func decodePrivatePttStoreResponse(c *QQClient, _ uint16, payload []byte) (interface{}, error) { - rsp := cmd0x346.C346RspBody{} - if err := proto.Unmarshal(payload, &rsp); err != nil { - c.Error("unmarshal cmd0x346 rsp body error: %v", err) - return nil, errors.Wrap(err, "unmarshal cmd0x346 rsp body error") - } - if rsp.ApplyUploadRsp == nil { - c.Error("decode apply upload 500 error: apply rsp is nil.") - return nil, errors.New("apply rsp is nil") - } - if rsp.ApplyUploadRsp.RetCode != 0 { - c.Error("decode apply upload 500 error: %v", rsp.ApplyUploadRsp.RetCode) - return nil, errors.Errorf("apply upload rsp error: %d", rsp.ApplyUploadRsp.RetCode) - } - if rsp.ApplyUploadRsp.BoolFileExist { - return pttUploadResponse{IsExists: true}, nil - } - var port []int32 - for range rsp.ApplyUploadRsp.UploadipList { - port = append(port, rsp.ApplyUploadRsp.UploadPort) - } - return pttUploadResponse{ - UploadKey: rsp.ApplyUploadRsp.UploadKey, - UploadIp: rsp.ApplyUploadRsp.UploadipList, - UploadPort: port, - FileKey: rsp.ApplyUploadRsp.Uuid, - }, nil + return payload } // PttCenterSvr.ShortVideoDownReq @@ -375,3 +343,19 @@ func decodeGroupShortVideoUploadResponse(_ *QQClient, _ uint16, payload []byte) } return rsp.PttShortVideoUploadRsp, nil } + +func constructPTTExtraInfo(codec, length int32) []byte { + return binary.NewWriterF(func(w *binary.Writer) { + w.WriteByte(3) + w.WriteByte(8) + w.WriteUInt16(4) + w.WriteUInt32(uint32(codec)) + w.WriteByte(9) + w.WriteUInt16(4) + w.WriteUInt32(uint32(14)) // length 时间 + w.WriteByte(10) + info := []byte{0x08, 0x00, 0x28, 0x00, 0x38, 0x00} // todo + w.WriteUInt16(uint16(len(info))) + w.Write(info) + }) +}