1
0
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:
wdvxdr 2022-06-20 10:16:19 +08:00
parent 2a1fd324ca
commit 6dc99526ee
No known key found for this signature in database
GPG Key ID: 703F8C071DE7A1B6
2 changed files with 63 additions and 104 deletions

View File

@ -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) {

View File

@ -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
RemoteFolder string
size int64 size int64
md5 []byte md5 []byte
sha1 []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)
} else {
seq, pkt = c.buildGroupFileUploadReqPacket(target.PrimaryID, file)
}
i, err := c.sendAndWait(seq, pkt)
if err != nil { if err != nil {
return err return errors.Wrap(err, "query upload failed")
} }
rsp = i.(*fileUploadRsp) rsp := i.(*fileUploadRsp)
}
if !rsp.existed { 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
} }