diff --git a/client/guild_msg.go b/client/guild_msg.go index fde0574a..b7b7f412 100644 --- a/client/guild_msg.go +++ b/client/guild_msg.go @@ -15,7 +15,6 @@ import ( "github.com/Mrs4s/MiraiGo/client/pb/channel" "github.com/Mrs4s/MiraiGo/client/pb/cmd0x388" "github.com/Mrs4s/MiraiGo/client/pb/msg" - "github.com/Mrs4s/MiraiGo/client/pb/pttcenter" "github.com/Mrs4s/MiraiGo/internal/proto" "github.com/Mrs4s/MiraiGo/message" "github.com/Mrs4s/MiraiGo/utils" @@ -346,71 +345,3 @@ func (s *GuildService) parseGuildChannelMessage(msg *channel.ChannelMsgContent) Elements: message.ParseMessageElems(msg.Body.RichText.Elems), } } - -// PttCenterSvr.GroupShortVideoUpReq -func (c *QQClient) buildPttGuildVideoUpReq(videoHash, thumbHash []byte, guildId, channelId int64, videoSize, thumbSize int64) (uint16, []byte) { - 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) -} - -func (c *QQClient) UploadGuildShortVideo(guildId, channelId uint64, video, thumb io.ReadSeeker) (*message.ShortVideoElement, error) { - // todo: combine with group short video upload - videoHash, videoLen := utils.ComputeMd5AndLength(video) - thumbHash, thumbLen := utils.ComputeMd5AndLength(thumb) - - key := string(videoHash) + string(thumbHash) - pttWaiter.Wait(key) - defer pttWaiter.Done(key) - - i, err := c.sendAndWait(c.buildPttGuildVideoUpReq(videoHash, thumbHash, int64(guildId), int64(channelId), videoLen, thumbLen)) - if err != nil { - return nil, errors.Wrap(err, "upload req error") - } - rsp := i.(*pttcenter.ShortVideoUploadRsp) - if rsp.FileExists == 1 { - return &message.ShortVideoElement{ - Uuid: []byte(rsp.FileId), - Size: int32(videoLen), - ThumbSize: int32(thumbLen), - Md5: videoHash, - ThumbMd5: thumbHash, - Guild: true, - }, nil - } - req := c.buildPttGroupShortVideoProto(videoHash, thumbHash, int64(guildId), videoLen, thumbLen, 4).PttShortVideoUploadReq - req.BusinessType = 4601 - req.ToUin = int64(channelId) - ext, _ := proto.Marshal(req) - multi := utils.MultiReadSeeker(thumb, video) - - hwRsp, err := c.highwaySession.UploadBDH(highway.BdhInput{ - CommandID: 89, - Body: multi, - Ticket: c.highwaySession.SigSession, - Ext: ext, - Encrypt: true, - }) - if err != nil { - return nil, errors.Wrap(err, "upload video file error") - } - - if len(hwRsp) == 0 { - return nil, errors.New("resp is empty") - } - rsp = &pttcenter.ShortVideoUploadRsp{} - if err = proto.Unmarshal(hwRsp, rsp); err != nil { - return nil, errors.Wrap(err, "decode error") - } - return &message.ShortVideoElement{ - Uuid: []byte(rsp.FileId), - Size: int32(videoLen), - ThumbSize: int32(thumbLen), - Md5: videoHash, - ThumbMd5: thumbHash, - Guild: true, - }, nil -} diff --git a/client/ptt.go b/client/ptt.go index 5c1e74c8..68485467 100644 --- a/client/ptt.go +++ b/client/ptt.go @@ -132,9 +132,9 @@ func (c *QQClient) UploadPrivatePtt(target int64, voice io.ReadSeeker) (*message }, nil } -// UploadGroupShortVideo 将视频和封面上传到服务器, 返回 message.ShortVideoElement 可直接发送 +// UploadShortVideo 将视频和封面上传到服务器, 返回 message.ShortVideoElement 可直接发送 // thread 上传线程数 -func (c *QQClient) UploadGroupShortVideo(groupCode int64, video, thumb io.ReadSeeker, thread int) (*message.ShortVideoElement, error) { +func (c *QQClient) UploadShortVideo(target message.Source, video, thumb io.ReadSeeker, thread int) (*message.ShortVideoElement, error) { videoHash, videoLen := utils.ComputeMd5AndLength(video) thumbHash, thumbLen := utils.ComputeMd5AndLength(thumb) @@ -142,27 +142,33 @@ 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.sendAndWait(c.buildPttGroupShortVideoUploadReqPacket(target, videoHash, thumbHash, videoLen, thumbLen)) if err != nil { return nil, errors.Wrap(err, "upload req error") } rsp := i.(*pttcenter.ShortVideoUploadRsp) - if rsp.FileExists == 1 { - return &message.ShortVideoElement{ - Uuid: []byte(rsp.FileId), - Size: int32(videoLen), - ThumbSize: int32(thumbLen), - Md5: videoHash, - ThumbMd5: thumbHash, - }, nil + videoElement := &message.ShortVideoElement{ + Size: int32(videoLen), + ThumbSize: int32(thumbLen), + Md5: videoHash, + ThumbMd5: thumbHash, + Guild: target.SourceType == message.SourceGuildChannel, + } + if rsp.FileExists == 1 { + videoElement.Uuid = []byte(rsp.FileId) + return videoElement, nil } - ext, _ := proto.Marshal(c.buildPttGroupShortVideoProto(videoHash, thumbHash, groupCode, videoLen, thumbLen, 1).PttShortVideoUploadReq) var hwRsp []byte + cmd := int32(25) + if target.SourceType == message.SourceGuildChannel { + cmd = 89 + } + ext, _ := proto.Marshal(c.buildPttShortVideoProto(target, videoHash, thumbHash, videoLen, thumbLen).PttShortVideoUploadReq) if thread > 1 { sum, _ := utils.ComputeMd5AndLength(utils.MultiReadSeeker(thumb, video)) input := highway.BdhMultiThreadInput{ - CommandID: 25, + CommandID: cmd, Body: utils.ReaderAtFrom2ReadSeeker(thumb, video), Size: videoLen + thumbLen, Sum: sum, @@ -174,7 +180,7 @@ func (c *QQClient) UploadGroupShortVideo(groupCode int64, video, thumb io.ReadSe } else { multi := utils.MultiReadSeeker(thumb, video) input := highway.BdhInput{ - CommandID: 25, + CommandID: cmd, Body: multi, Ticket: c.highwaySession.SigSession, Ext: ext, @@ -192,13 +198,8 @@ func (c *QQClient) UploadGroupShortVideo(groupCode int64, video, thumb io.ReadSe if err = proto.Unmarshal(hwRsp, rsp); err != nil { return nil, errors.Wrap(err, "decode error") } - return &message.ShortVideoElement{ - Uuid: []byte(rsp.FileId), - Size: int32(videoLen), - ThumbSize: int32(thumbLen), - Md5: videoHash, - ThumbMd5: thumbHash, - }, nil + videoElement.Uuid = []byte(rsp.FileId) + return videoElement, nil } func (c *QQClient) GetShortVideoUrl(uuid, md5 []byte) string { @@ -261,15 +262,19 @@ func (c *QQClient) buildPttShortVideoDownReqPacket(uuid, md5 []byte) (uint16, [] return seq, packet } -func (c *QQClient) buildPttGroupShortVideoProto(videoHash, thumbHash []byte, toUin, videoSize, thumbSize int64, chattype int32) *pttcenter.ShortVideoReqBody { +func (c *QQClient) buildPttShortVideoProto(target message.Source, videoHash, thumbHash []byte, videoSize, thumbSize int64) *pttcenter.ShortVideoReqBody { seq := c.nextSeq() - return &pttcenter.ShortVideoReqBody{ + chatType := int32(1) + if target.SourceType == message.SourceGuildChannel { + chatType = 4 + } + body := &pttcenter.ShortVideoReqBody{ Cmd: 300, Seq: int32(seq), PttShortVideoUploadReq: &pttcenter.ShortVideoUploadReq{ FromUin: c.Uin, - ToUin: toUin, - ChatType: chattype, + ToUin: target.PrimaryID, + ChatType: chatType, ClientType: 2, Info: &pttcenter.ShortVideoFileInfo{ FileName: hex.EncodeToString(videoHash) + ".mp4", @@ -282,7 +287,7 @@ func (c *QQClient) buildPttGroupShortVideoProto(videoHash, thumbHash []byte, toU FileTime: 120, ThumbFileSize: thumbSize, }, - GroupCode: toUin, + GroupCode: target.PrimaryID, SupportLargeSize: 1, }, ExtensionReq: []*pttcenter.ShortVideoExtensionReq{ @@ -292,11 +297,18 @@ func (c *QQClient) buildPttGroupShortVideoProto(videoHash, thumbHash []byte, toU }, }, } + if target.SourceType == message.SourceGuildChannel { + body.PttShortVideoUploadReq.BusinessType = 4601 + body.PttShortVideoUploadReq.ToUin = target.SecondaryID + body.ExtensionReq[0].SubBusiType = 4601 + } + return body } // PttCenterSvr.GroupShortVideoUpReq -func (c *QQClient) buildPttGroupShortVideoUploadReqPacket(videoHash, thumbHash []byte, toUin, videoSize, thumbSize int64) (uint16, []byte) { - payload, _ := proto.Marshal(c.buildPttGroupShortVideoProto(videoHash, thumbHash, toUin, videoSize, thumbSize, 1)) +func (c *QQClient) buildPttGroupShortVideoUploadReqPacket(target message.Source, videoHash, thumbHash []byte, videoSize, thumbSize int64) (uint16, []byte) { + pb := c.buildPttShortVideoProto(target, videoHash, thumbHash, videoSize, thumbSize) + payload, _ := proto.Marshal(pb) return c.uniPacket("PttCenterSvr.GroupShortVideoUpReq", payload) } diff --git a/message/source.go b/message/source.go new file mode 100644 index 00000000..f41ddd84 --- /dev/null +++ b/message/source.go @@ -0,0 +1,18 @@ +package message + +type SourceType byte + +// MessageSourceType 常量 +const ( + SourcePrivate SourceType = 1 << iota + SourceGroup + SourceGuildChannel + SourceGuildDirect +) + +// Source 消息来源 +type Source struct { + SourceType SourceType + PrimaryID int64 // 群号/QQ号/guild_id + SecondaryID int64 // channel_id +} diff --git a/utils/sys.go b/utils/sys.go index 57080779..7ef22b45 100644 --- a/utils/sys.go +++ b/utils/sys.go @@ -4,8 +4,6 @@ import ( "crypto/md5" "errors" "io" - "reflect" - "unsafe" ) type multiReadSeeker struct { @@ -13,20 +11,6 @@ type multiReadSeeker struct { multiReader io.Reader } -func add(p unsafe.Pointer, x uintptr) unsafe.Pointer { - return unsafe.Pointer(uintptr(p) + x) -} - -func IsChanClosed(ch interface{}) bool { - if reflect.TypeOf(ch).Kind() != reflect.Chan { - panic("object is not a channel.") - } - return *(*uint32)( - add(*(*unsafe.Pointer)(add(unsafe.Pointer(&ch), unsafe.Sizeof(uintptr(0)))), - unsafe.Sizeof(uint(0))*2+unsafe.Sizeof(uintptr(0))+unsafe.Sizeof(uint16(0))), - ) > 0 -} - func ComputeMd5AndLength(r io.Reader) ([]byte, int64) { h := md5.New() length, _ := io.Copy(h, r)