1
0
mirror of https://github.com/Mrs4s/MiraiGo.git synced 2025-05-04 11:07:40 +08:00

client: combine upload group video and guild video

This commit is contained in:
wdvxdr 2022-02-21 17:31:05 +08:00
parent 9ef6c3cf3a
commit 1e32793eef
No known key found for this signature in database
GPG Key ID: 703F8C071DE7A1B6
4 changed files with 58 additions and 113 deletions

View File

@ -15,7 +15,6 @@ import (
"github.com/Mrs4s/MiraiGo/client/pb/channel" "github.com/Mrs4s/MiraiGo/client/pb/channel"
"github.com/Mrs4s/MiraiGo/client/pb/cmd0x388" "github.com/Mrs4s/MiraiGo/client/pb/cmd0x388"
"github.com/Mrs4s/MiraiGo/client/pb/msg" "github.com/Mrs4s/MiraiGo/client/pb/msg"
"github.com/Mrs4s/MiraiGo/client/pb/pttcenter"
"github.com/Mrs4s/MiraiGo/internal/proto" "github.com/Mrs4s/MiraiGo/internal/proto"
"github.com/Mrs4s/MiraiGo/message" "github.com/Mrs4s/MiraiGo/message"
"github.com/Mrs4s/MiraiGo/utils" "github.com/Mrs4s/MiraiGo/utils"
@ -346,71 +345,3 @@ func (s *GuildService) parseGuildChannelMessage(msg *channel.ChannelMsgContent)
Elements: message.ParseMessageElems(msg.Body.RichText.Elems), 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
}

View File

@ -132,9 +132,9 @@ func (c *QQClient) UploadPrivatePtt(target int64, voice io.ReadSeeker) (*message
}, nil }, nil
} }
// UploadGroupShortVideo 将视频和封面上传到服务器, 返回 message.ShortVideoElement 可直接发送 // UploadShortVideo 将视频和封面上传到服务器, 返回 message.ShortVideoElement 可直接发送
// thread 上传线程数 // 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) videoHash, videoLen := utils.ComputeMd5AndLength(video)
thumbHash, thumbLen := utils.ComputeMd5AndLength(thumb) thumbHash, thumbLen := utils.ComputeMd5AndLength(thumb)
@ -142,27 +142,33 @@ func (c *QQClient) UploadGroupShortVideo(groupCode int64, video, thumb io.ReadSe
pttWaiter.Wait(key) pttWaiter.Wait(key)
defer pttWaiter.Done(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 { if err != nil {
return nil, errors.Wrap(err, "upload req error") return nil, errors.Wrap(err, "upload req error")
} }
rsp := i.(*pttcenter.ShortVideoUploadRsp) rsp := i.(*pttcenter.ShortVideoUploadRsp)
if rsp.FileExists == 1 { videoElement := &message.ShortVideoElement{
return &message.ShortVideoElement{ Size: int32(videoLen),
Uuid: []byte(rsp.FileId), ThumbSize: int32(thumbLen),
Size: int32(videoLen), Md5: videoHash,
ThumbSize: int32(thumbLen), ThumbMd5: thumbHash,
Md5: videoHash, Guild: target.SourceType == message.SourceGuildChannel,
ThumbMd5: thumbHash, }
}, nil 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 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 { if thread > 1 {
sum, _ := utils.ComputeMd5AndLength(utils.MultiReadSeeker(thumb, video)) sum, _ := utils.ComputeMd5AndLength(utils.MultiReadSeeker(thumb, video))
input := highway.BdhMultiThreadInput{ input := highway.BdhMultiThreadInput{
CommandID: 25, CommandID: cmd,
Body: utils.ReaderAtFrom2ReadSeeker(thumb, video), Body: utils.ReaderAtFrom2ReadSeeker(thumb, video),
Size: videoLen + thumbLen, Size: videoLen + thumbLen,
Sum: sum, Sum: sum,
@ -174,7 +180,7 @@ func (c *QQClient) UploadGroupShortVideo(groupCode int64, video, thumb io.ReadSe
} else { } else {
multi := utils.MultiReadSeeker(thumb, video) multi := utils.MultiReadSeeker(thumb, video)
input := highway.BdhInput{ input := highway.BdhInput{
CommandID: 25, CommandID: cmd,
Body: multi, Body: multi,
Ticket: c.highwaySession.SigSession, Ticket: c.highwaySession.SigSession,
Ext: ext, Ext: ext,
@ -192,13 +198,8 @@ func (c *QQClient) UploadGroupShortVideo(groupCode int64, video, thumb io.ReadSe
if err = proto.Unmarshal(hwRsp, rsp); err != nil { if err = proto.Unmarshal(hwRsp, rsp); err != nil {
return nil, errors.Wrap(err, "decode error") return nil, errors.Wrap(err, "decode error")
} }
return &message.ShortVideoElement{ videoElement.Uuid = []byte(rsp.FileId)
Uuid: []byte(rsp.FileId), return videoElement, nil
Size: int32(videoLen),
ThumbSize: int32(thumbLen),
Md5: videoHash,
ThumbMd5: thumbHash,
}, nil
} }
func (c *QQClient) GetShortVideoUrl(uuid, md5 []byte) string { func (c *QQClient) GetShortVideoUrl(uuid, md5 []byte) string {
@ -261,15 +262,19 @@ func (c *QQClient) buildPttShortVideoDownReqPacket(uuid, md5 []byte) (uint16, []
return seq, packet 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() seq := c.nextSeq()
return &pttcenter.ShortVideoReqBody{ chatType := int32(1)
if target.SourceType == message.SourceGuildChannel {
chatType = 4
}
body := &pttcenter.ShortVideoReqBody{
Cmd: 300, Cmd: 300,
Seq: int32(seq), Seq: int32(seq),
PttShortVideoUploadReq: &pttcenter.ShortVideoUploadReq{ PttShortVideoUploadReq: &pttcenter.ShortVideoUploadReq{
FromUin: c.Uin, FromUin: c.Uin,
ToUin: toUin, ToUin: target.PrimaryID,
ChatType: chattype, ChatType: chatType,
ClientType: 2, ClientType: 2,
Info: &pttcenter.ShortVideoFileInfo{ Info: &pttcenter.ShortVideoFileInfo{
FileName: hex.EncodeToString(videoHash) + ".mp4", FileName: hex.EncodeToString(videoHash) + ".mp4",
@ -282,7 +287,7 @@ func (c *QQClient) buildPttGroupShortVideoProto(videoHash, thumbHash []byte, toU
FileTime: 120, FileTime: 120,
ThumbFileSize: thumbSize, ThumbFileSize: thumbSize,
}, },
GroupCode: toUin, GroupCode: target.PrimaryID,
SupportLargeSize: 1, SupportLargeSize: 1,
}, },
ExtensionReq: []*pttcenter.ShortVideoExtensionReq{ 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 // PttCenterSvr.GroupShortVideoUpReq
func (c *QQClient) buildPttGroupShortVideoUploadReqPacket(videoHash, thumbHash []byte, toUin, videoSize, thumbSize int64) (uint16, []byte) { func (c *QQClient) buildPttGroupShortVideoUploadReqPacket(target message.Source, videoHash, thumbHash []byte, videoSize, thumbSize int64) (uint16, []byte) {
payload, _ := proto.Marshal(c.buildPttGroupShortVideoProto(videoHash, thumbHash, toUin, videoSize, thumbSize, 1)) pb := c.buildPttShortVideoProto(target, videoHash, thumbHash, videoSize, thumbSize)
payload, _ := proto.Marshal(pb)
return c.uniPacket("PttCenterSvr.GroupShortVideoUpReq", payload) return c.uniPacket("PttCenterSvr.GroupShortVideoUpReq", payload)
} }

18
message/source.go Normal file
View File

@ -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
}

View File

@ -4,8 +4,6 @@ import (
"crypto/md5" "crypto/md5"
"errors" "errors"
"io" "io"
"reflect"
"unsafe"
) )
type multiReadSeeker struct { type multiReadSeeker struct {
@ -13,20 +11,6 @@ type multiReadSeeker struct {
multiReader io.Reader 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) { func ComputeMd5AndLength(r io.Reader) ([]byte, int64) {
h := md5.New() h := md5.New()
length, _ := io.Copy(h, r) length, _ := io.Copy(h, r)