mirror of
https://github.com/Mrs4s/MiraiGo.git
synced 2025-05-04 19:17:38 +08:00
client: change use _UploadFile to upload group file
This commit is contained in:
parent
2a1fd324ca
commit
6dc99526ee
@ -3,18 +3,15 @@ package client
|
|||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
|
||||||
"os"
|
"os"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/Mrs4s/MiraiGo/client/internal/highway"
|
|
||||||
"github.com/Mrs4s/MiraiGo/client/internal/network"
|
"github.com/Mrs4s/MiraiGo/client/internal/network"
|
||||||
"github.com/Mrs4s/MiraiGo/client/pb/exciting"
|
|
||||||
"github.com/Mrs4s/MiraiGo/client/pb/oidb"
|
"github.com/Mrs4s/MiraiGo/client/pb/oidb"
|
||||||
"github.com/Mrs4s/MiraiGo/internal/proto"
|
"github.com/Mrs4s/MiraiGo/internal/proto"
|
||||||
"github.com/Mrs4s/MiraiGo/utils"
|
"github.com/Mrs4s/MiraiGo/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@ -53,8 +50,6 @@ type (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
var fsWaiter = utils.NewUploadWaiter()
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
decoders["OidbSvc.0x6d8_1"] = decodeOIDB6d81Response
|
decoders["OidbSvc.0x6d8_1"] = decodeOIDB6d81Response
|
||||||
decoders["OidbSvc.0x6d6_0"] = decodeOIDB6d60Response
|
decoders["OidbSvc.0x6d6_0"] = decodeOIDB6d60Response
|
||||||
@ -160,80 +155,21 @@ func (fs *GroupFileSystem) GetFilesByFolder(folderID string) ([]*GroupFile, []*G
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fs *GroupFileSystem) UploadFile(p, name, folderId string) error {
|
func (fs *GroupFileSystem) UploadFile(p, name, folderId string) error {
|
||||||
// 同文件等待其他线程上传
|
|
||||||
fsWaiter.Wait(p)
|
|
||||||
defer fsWaiter.Done(p)
|
|
||||||
|
|
||||||
file, err := os.OpenFile(p, os.O_RDONLY, 0o666)
|
file, err := os.OpenFile(p, os.O_RDONLY, 0o666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "open file error")
|
return errors.Wrap(err, "open file error")
|
||||||
}
|
}
|
||||||
defer func() { _ = file.Close() }()
|
defer func() { _ = file.Close() }()
|
||||||
f := &FileResource{
|
f := &LocalFile{
|
||||||
FileName: name,
|
FileName: name,
|
||||||
Body: file,
|
Body: file,
|
||||||
|
RemoteFolder: folderId,
|
||||||
}
|
}
|
||||||
f.init()
|
target := message.Source{
|
||||||
i, err := fs.client.sendAndWait(fs.client.buildGroupFileUploadReqPacket(folderId, fs.GroupCode, f))
|
SourceType: message.SourceGroup,
|
||||||
if err != nil {
|
PrimaryID: fs.GroupCode,
|
||||||
return errors.Wrap(err, "query upload failed")
|
|
||||||
}
|
}
|
||||||
rsp := i.(*oidb.UploadFileRspBody)
|
return fs.client._UploadFile(target, f)
|
||||||
if !rsp.BoolFileExist.Unwrap() {
|
|
||||||
if len(rsp.UploadIpLanV4) == 0 {
|
|
||||||
return errors.New("server requires unsupported ftn upload")
|
|
||||||
}
|
|
||||||
ext, _ := proto.Marshal(&exciting.FileUploadExt{
|
|
||||||
Unknown1: proto.Int32(100),
|
|
||||||
Unknown2: proto.Int32(1),
|
|
||||||
Entry: &exciting.FileUploadEntry{
|
|
||||||
BusiBuff: &exciting.ExcitingBusiInfo{
|
|
||||||
BusId: rsp.BusId,
|
|
||||||
SenderUin: proto.Some(fs.client.Uin),
|
|
||||||
ReceiverUin: proto.Some(fs.GroupCode),
|
|
||||||
GroupCode: proto.Some(fs.GroupCode),
|
|
||||||
},
|
|
||||||
FileEntry: &exciting.ExcitingFileEntry{
|
|
||||||
FileSize: proto.Some(f.size),
|
|
||||||
Md5: f.md5,
|
|
||||||
Sha1: f.sha1,
|
|
||||||
FileId: []byte(rsp.FileId.Unwrap()),
|
|
||||||
UploadKey: rsp.CheckKey,
|
|
||||||
},
|
|
||||||
ClientInfo: &exciting.ExcitingClientInfo{
|
|
||||||
ClientType: proto.Int32(2),
|
|
||||||
AppId: proto.String(fmt.Sprint(fs.client.version.AppId)),
|
|
||||||
TerminalType: proto.Int32(2),
|
|
||||||
ClientVer: proto.String("9e9c09dc"),
|
|
||||||
Unknown: proto.Int32(4),
|
|
||||||
},
|
|
||||||
FileNameInfo: &exciting.ExcitingFileNameInfo{FileName: proto.Some(name)},
|
|
||||||
Host: &exciting.ExcitingHostConfig{Hosts: []*exciting.ExcitingHostInfo{
|
|
||||||
{
|
|
||||||
Url: &exciting.ExcitingUrlInfo{
|
|
||||||
Unknown: proto.Int32(1),
|
|
||||||
Host: proto.Some(rsp.UploadIpLanV4[0]),
|
|
||||||
},
|
|
||||||
Port: rsp.UploadPort,
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
Unknown3: proto.Int32(0),
|
|
||||||
})
|
|
||||||
input := highway.Transaction{
|
|
||||||
CommandID: 71,
|
|
||||||
Body: file,
|
|
||||||
Size: f.size,
|
|
||||||
Sum: f.md5,
|
|
||||||
Ticket: fs.client.highwaySession.SigSession,
|
|
||||||
Ext: ext,
|
|
||||||
}
|
|
||||||
if _, err = fs.client.highwaySession.UploadExciting(input); err != nil {
|
|
||||||
return errors.Wrap(err, "upload failed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_, pkt := fs.client.buildGroupFileFeedsRequest(fs.GroupCode, rsp.FileId.Unwrap(), rsp.BusId.Unwrap(), rand.Int31())
|
|
||||||
return fs.client.sendPacket(pkt)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fs *GroupFileSystem) GetDownloadUrl(file *GroupFile) string {
|
func (fs *GroupFileSystem) GetDownloadUrl(file *GroupFile) string {
|
||||||
@ -271,13 +207,13 @@ func (fs *GroupFileSystem) DeleteFile(parentFolderID, fileId string, busId int32
|
|||||||
return i.(string)
|
return i.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *QQClient) buildGroupFileUploadReqPacket(parentFolderID string, groupCode int64, file *FileResource) (uint16, []byte) {
|
func (c *QQClient) buildGroupFileUploadReqPacket(groupCode int64, file *LocalFile) (uint16, []byte) {
|
||||||
body := &oidb.D6D6ReqBody{UploadFileReq: &oidb.UploadFileReqBody{
|
body := &oidb.D6D6ReqBody{UploadFileReq: &oidb.UploadFileReqBody{
|
||||||
GroupCode: proto.Some(groupCode),
|
GroupCode: proto.Some(groupCode),
|
||||||
AppId: proto.Int32(3),
|
AppId: proto.Int32(3),
|
||||||
BusId: proto.Int32(102),
|
BusId: proto.Int32(102),
|
||||||
Entrance: proto.Int32(5),
|
Entrance: proto.Int32(5),
|
||||||
ParentFolderId: proto.Some(parentFolderID),
|
ParentFolderId: proto.Some(file.RemoteFolder),
|
||||||
FileName: proto.Some(file.FileName),
|
FileName: proto.Some(file.FileName),
|
||||||
LocalPath: proto.String("/storage/emulated/0/Pictures/files/s/" + file.FileName),
|
LocalPath: proto.String("/storage/emulated/0/Pictures/files/s/" + file.FileName),
|
||||||
Int64FileSize: proto.Some(file.size),
|
Int64FileSize: proto.Some(file.size),
|
||||||
@ -437,7 +373,16 @@ func decodeOIDB6d60Response(_ *QQClient, _ *network.IncomingPacketInfo, payload
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return rsp.UploadFileRsp, nil
|
u := rsp.UploadFileRsp
|
||||||
|
r := &fileUploadRsp{
|
||||||
|
Existed: u.BoolFileExist.Unwrap(),
|
||||||
|
BusID: u.BusId.Unwrap(),
|
||||||
|
Uuid: []byte(u.FileId.Unwrap()),
|
||||||
|
UploadKey: u.CheckKey,
|
||||||
|
UploadIpLanV4: u.UploadIpLanV4,
|
||||||
|
UploadPort: u.UploadPort.Unwrap(),
|
||||||
|
}
|
||||||
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeOIDB6d7Response(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (any, error) {
|
func decodeOIDB6d7Response(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (any, error) {
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"math/rand"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
@ -14,32 +15,34 @@ import (
|
|||||||
"github.com/Mrs4s/MiraiGo/client/pb/exciting"
|
"github.com/Mrs4s/MiraiGo/client/pb/exciting"
|
||||||
"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"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
decoders["OfflineFilleHandleSvr.pb_ftn_CMD_REQ_APPLY_UPLOAD_V3-1700"] = decodePrivateFileUploadReq
|
decoders["OfflineFilleHandleSvr.pb_ftn_CMD_REQ_APPLY_UPLOAD_V3-1700"] = decodePrivateFileUploadReq
|
||||||
}
|
}
|
||||||
|
|
||||||
type FileResource struct {
|
type LocalFile struct {
|
||||||
FileName string
|
FileName string
|
||||||
Body io.ReadSeeker // FileResource content body
|
Body io.ReadSeeker // LocalFile content body
|
||||||
size int64
|
RemoteFolder string
|
||||||
md5 []byte
|
size int64
|
||||||
sha1 []byte
|
md5 []byte
|
||||||
|
sha1 []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type fileUploadRsp struct {
|
type fileUploadRsp struct {
|
||||||
existed bool
|
Existed bool
|
||||||
busid int32
|
BusID int32
|
||||||
uuid []byte
|
Uuid []byte
|
||||||
uploadKey []byte
|
UploadKey []byte
|
||||||
|
|
||||||
// upload group file need
|
// upload group file need
|
||||||
UploadIpLanV4 []string
|
UploadIpLanV4 []string
|
||||||
UploadPort int32
|
UploadPort int32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FileResource) init() {
|
func (f *LocalFile) init() {
|
||||||
md5H := md5.New()
|
md5H := md5.New()
|
||||||
sha1H := sha1.New()
|
sha1H := sha1.New()
|
||||||
|
|
||||||
@ -52,28 +55,35 @@ func (f *FileResource) init() {
|
|||||||
f.sha1 = sha1H.Sum(nil)
|
f.sha1 = sha1H.Sum(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *QQClient) _UploadFile(target message.Source, file *FileResource) error {
|
var fsWaiter = utils.NewUploadWaiter()
|
||||||
|
|
||||||
|
func (c *QQClient) _UploadFile(target message.Source, file *LocalFile) error {
|
||||||
file.init()
|
file.init()
|
||||||
// 同文件等待其他线程上传
|
// 同文件等待其他线程上传
|
||||||
fkey := string(file.sha1)
|
fkey := string(file.sha1)
|
||||||
fsWaiter.Wait(fkey)
|
fsWaiter.Wait(fkey)
|
||||||
defer fsWaiter.Done(fkey)
|
defer fsWaiter.Done(fkey)
|
||||||
|
|
||||||
var rsp *fileUploadRsp
|
var seq uint16
|
||||||
|
var pkt []byte
|
||||||
if target.SourceType == message.SourcePrivate {
|
if target.SourceType == message.SourcePrivate {
|
||||||
i, err := c.sendAndWait(c.buildPrivateFileUploadReqPacket(target, file))
|
seq, pkt = c.buildPrivateFileUploadReqPacket(target, file)
|
||||||
if err != nil {
|
} else {
|
||||||
return err
|
seq, pkt = c.buildGroupFileUploadReqPacket(target.PrimaryID, file)
|
||||||
}
|
|
||||||
rsp = i.(*fileUploadRsp)
|
|
||||||
}
|
}
|
||||||
if !rsp.existed {
|
i, err := c.sendAndWait(seq, pkt)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "query upload failed")
|
||||||
|
}
|
||||||
|
rsp := i.(*fileUploadRsp)
|
||||||
|
|
||||||
|
if !rsp.Existed {
|
||||||
ext := &exciting.FileUploadExt{
|
ext := &exciting.FileUploadExt{
|
||||||
Unknown1: proto.Int32(100),
|
Unknown1: proto.Int32(100),
|
||||||
Unknown2: proto.Int32(2),
|
Unknown2: proto.Int32(2),
|
||||||
Entry: &exciting.FileUploadEntry{
|
Entry: &exciting.FileUploadEntry{
|
||||||
BusiBuff: &exciting.ExcitingBusiInfo{
|
BusiBuff: &exciting.ExcitingBusiInfo{
|
||||||
BusId: proto.Int32(rsp.busid),
|
BusId: proto.Int32(rsp.BusID),
|
||||||
SenderUin: proto.Some(c.Uin),
|
SenderUin: proto.Some(c.Uin),
|
||||||
ReceiverUin: proto.Some(target.PrimaryID),
|
ReceiverUin: proto.Some(target.PrimaryID),
|
||||||
GroupCode: proto.Int64(0),
|
GroupCode: proto.Int64(0),
|
||||||
@ -82,8 +92,8 @@ func (c *QQClient) _UploadFile(target message.Source, file *FileResource) error
|
|||||||
FileSize: proto.Some(file.size),
|
FileSize: proto.Some(file.size),
|
||||||
Md5: file.md5,
|
Md5: file.md5,
|
||||||
Sha1: file.sha1,
|
Sha1: file.sha1,
|
||||||
FileId: rsp.uuid,
|
FileId: rsp.Uuid,
|
||||||
UploadKey: rsp.uploadKey,
|
UploadKey: rsp.UploadKey,
|
||||||
},
|
},
|
||||||
ClientInfo: &exciting.ExcitingClientInfo{
|
ClientInfo: &exciting.ExcitingClientInfo{
|
||||||
ClientType: proto.Int32(2),
|
ClientType: proto.Int32(2),
|
||||||
@ -133,10 +143,14 @@ func (c *QQClient) _UploadFile(target message.Source, file *FileResource) error
|
|||||||
return errors.Wrap(err, "upload failed")
|
return errors.Wrap(err, "upload failed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
if target.SourceType == message.SourceGroup {
|
||||||
|
_, pkt := c.buildGroupFileFeedsRequest(target.PrimaryID, string(rsp.Uuid), rsp.BusID, rand.Int31())
|
||||||
|
return c.sendPacket(pkt)
|
||||||
|
}
|
||||||
|
return errors.New("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *QQClient) buildPrivateFileUploadReqPacket(target message.Source, file *FileResource) (uint16, []byte) {
|
func (c *QQClient) buildPrivateFileUploadReqPacket(target message.Source, file *LocalFile) (uint16, []byte) {
|
||||||
req := cmd0x346.C346ReqBody{
|
req := cmd0x346.C346ReqBody{
|
||||||
Cmd: 1700,
|
Cmd: 1700,
|
||||||
Seq: c.nextFriendSeq(),
|
Seq: c.nextFriendSeq(),
|
||||||
@ -167,10 +181,10 @@ func decodePrivateFileUploadReq(_ *QQClient, _ *network.IncomingPacketInfo, payl
|
|||||||
}
|
}
|
||||||
v3 := rsp.ApplyUploadRspV3
|
v3 := rsp.ApplyUploadRspV3
|
||||||
r := &fileUploadRsp{
|
r := &fileUploadRsp{
|
||||||
existed: v3.BoolFileExist,
|
Existed: v3.BoolFileExist,
|
||||||
busid: 3,
|
BusID: 3,
|
||||||
uuid: v3.Uuid,
|
Uuid: v3.Uuid,
|
||||||
uploadKey: v3.MediaPlateformUploadKey,
|
UploadKey: v3.MediaPlateformUploadKey,
|
||||||
}
|
}
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user