1
0
mirror of https://github.com/Mrs4s/MiraiGo.git synced 2025-05-05 03:23:50 +08:00

Merge pull request #130 from wdvxdr1123/patch/ptt

fix private ptt
This commit is contained in:
Mrs4s 2021-03-02 17:17:01 +08:00 committed by GitHub
commit a48d1caac1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 60 additions and 77 deletions

View File

@ -122,31 +122,30 @@ type loginSigInfo struct {
} }
var decoders = map[string]func(*QQClient, uint16, []byte) (interface{}, error){ var decoders = map[string]func(*QQClient, uint16, []byte) (interface{}, error){
"wtlogin.login": decodeLoginResponse, "wtlogin.login": decodeLoginResponse,
"wtlogin.exchange_emp": decodeExchangeEmpResponse, "wtlogin.exchange_emp": decodeExchangeEmpResponse,
"StatSvc.register": decodeClientRegisterResponse, "StatSvc.register": decodeClientRegisterResponse,
"StatSvc.ReqMSFOffline": decodeMSFOfflinePacket, "StatSvc.ReqMSFOffline": decodeMSFOfflinePacket,
"MessageSvc.PushNotify": decodeSvcNotify, "MessageSvc.PushNotify": decodeSvcNotify,
"OnlinePush.ReqPush": decodeOnlinePushReqPacket, "OnlinePush.ReqPush": decodeOnlinePushReqPacket,
"OnlinePush.PbPushTransMsg": decodeOnlinePushTransPacket, "OnlinePush.PbPushTransMsg": decodeOnlinePushTransPacket,
"ConfigPushSvc.PushReq": decodePushReqPacket, "ConfigPushSvc.PushReq": decodePushReqPacket,
"MessageSvc.PbGetMsg": decodeMessageSvcPacket, "MessageSvc.PbGetMsg": decodeMessageSvcPacket,
"MessageSvc.PushForceOffline": decodeForceOfflinePacket, "MessageSvc.PushForceOffline": decodeForceOfflinePacket,
"PbMessageSvc.PbMsgWithDraw": decodeMsgWithDrawResponse, "PbMessageSvc.PbMsgWithDraw": decodeMsgWithDrawResponse,
"friendlist.getFriendGroupList": decodeFriendGroupListResponse, "friendlist.getFriendGroupList": decodeFriendGroupListResponse,
"friendlist.GetTroopListReqV2": decodeGroupListResponse, "friendlist.GetTroopListReqV2": decodeGroupListResponse,
"friendlist.GetTroopMemberListReq": decodeGroupMemberListResponse, "friendlist.GetTroopMemberListReq": decodeGroupMemberListResponse,
"group_member_card.get_group_member_card_info": decodeGroupMemberInfoResponse, "group_member_card.get_group_member_card_info": decodeGroupMemberInfoResponse,
"PttStore.GroupPttUp": decodeGroupPttStoreResponse, "PttStore.GroupPttUp": decodeGroupPttStoreResponse,
"LongConn.OffPicUp": decodeOffPicUpResponse, "LongConn.OffPicUp": decodeOffPicUpResponse,
"ProfileService.Pb.ReqSystemMsgNew.Group": decodeSystemMsgGroupPacket, "ProfileService.Pb.ReqSystemMsgNew.Group": decodeSystemMsgGroupPacket,
"ProfileService.Pb.ReqSystemMsgNew.Friend": decodeSystemMsgFriendPacket, "ProfileService.Pb.ReqSystemMsgNew.Friend": decodeSystemMsgFriendPacket,
"OidbSvc.0xe07_0": decodeImageOcrResponse, "OidbSvc.0xe07_0": decodeImageOcrResponse,
"OidbSvc.0xd79": decodeWordSegmentation, "OidbSvc.0xd79": decodeWordSegmentation,
"OidbSvc.0x990": decodeTranslateResponse, "OidbSvc.0x990": decodeTranslateResponse,
"SummaryCard.ReqSummaryCard": decodeSummaryCardResponse, "SummaryCard.ReqSummaryCard": decodeSummaryCardResponse,
"LightAppSvc.mini_app_info.GetAppInfoById": decodeAppInfoResponse, "LightAppSvc.mini_app_info.GetAppInfoById": decodeAppInfoResponse,
"PttCenterSvr.pb_pttCenter_CMD_REQ_APPLY_UPLOAD-500": decodePrivatePttStoreResponse,
} }
func init() { func init() {

View File

@ -1,6 +1,7 @@
package client package client
import ( import (
"bytes"
"crypto/md5" "crypto/md5"
"encoding/hex" "encoding/hex"
"io" "io"
@ -60,33 +61,31 @@ func (c *QQClient) UploadGroupPtt(groupCode int64, voice io.ReadSeeker) (*messag
// UploadPrivatePtt 将语音数据使用好友语音通道上传到服务器, 返回 message.PrivateVoiceElement 可直接发送 // UploadPrivatePtt 将语音数据使用好友语音通道上传到服务器, 返回 message.PrivateVoiceElement 可直接发送
func (c *QQClient) UploadPrivatePtt(target int64, voice []byte) (*message.PrivateVoiceElement, error) { func (c *QQClient) UploadPrivatePtt(target int64, voice []byte) (*message.PrivateVoiceElement, error) {
h := md5.Sum(voice) 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 { if err != nil {
return nil, err return nil, err
} }
rsp := i.(pttUploadResponse) if len(rsp) == 0 {
if rsp.IsExists { return nil, errors.New("miss rsp")
goto ok
} }
for i, ip := range rsp.UploadIp { pkt := cmd0x346.C346RspBody{}
err := c.uploadPtt(ip, rsp.UploadPort[i], rsp.UploadKey, rsp.FileKey, voice, h[:]) if err = proto.Unmarshal(rsp, &pkt); err != nil {
if err != nil { return nil, errors.Wrap(err, "failed to unmarshal protobuf message")
continue }
} if pkt.ApplyUploadRsp == nil {
goto ok return nil, errors.New("miss apply upload rsp")
} }
return nil, errors.New("upload failed")
ok:
return &message.PrivateVoiceElement{ return &message.PrivateVoiceElement{
Ptt: &msg.Ptt{ Ptt: &msg.Ptt{
FileType: proto.Int32(4), FileType: proto.Int32(4),
SrcUin: &c.Uin, SrcUin: &c.Uin,
FileMd5: h[:], FileUuid: pkt.ApplyUploadRsp.Uuid,
FileName: proto.String(hex.EncodeToString(h[:]) + ".amr"), FileMd5: h[:],
FileSize: proto.Int32(int32(len(voice))), FileName: proto.String(hex.EncodeToString(h[:]) + ".amr"),
FileKey: rsp.FileKey, FileSize: proto.Int32(int32(len(voice))),
// Reserve: constructPTTExtraInfo(1, int32(len(voice))), // todo length
BoolValid: proto.Bool(true), BoolValid: proto.Bool(true),
PbReserve: []byte{8, 0, 40, 0, 56, 0},
}}, nil }}, nil
} }
@ -291,7 +290,7 @@ func decodeGroupPttStoreResponse(_ *QQClient, _ uint16, payload []byte) (interfa
} }
// PttCenterSvr.pb_pttCenter_CMD_REQ_APPLY_UPLOAD-500 // 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() seq := c.nextSeq()
req := &cmd0x346.C346ReqBody{ req := &cmd0x346.C346ReqBody{
Cmd: 500, Cmd: 500,
@ -315,38 +314,7 @@ func (c *QQClient) buildPrivatePttStorePacket(target int64, md5 []byte, size, vo
}, },
} }
payload, _ := proto.Marshal(req) 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 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
} }
// PttCenterSvr.ShortVideoDownReq // PttCenterSvr.ShortVideoDownReq
@ -375,3 +343,19 @@ func decodeGroupShortVideoUploadResponse(_ *QQClient, _ uint16, payload []byte)
} }
return rsp.PttShortVideoUploadRsp, nil 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)
})
}