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:
parent
9ef6c3cf3a
commit
1e32793eef
@ -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
|
|
||||||
}
|
|
||||||
|
@ -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
18
message/source.go
Normal 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
|
||||||
|
}
|
16
utils/sys.go
16
utils/sys.go
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user