Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions drivers/189/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package _189

import (
"context"
"fmt"
"net/http"
"strings"

Expand Down Expand Up @@ -204,4 +205,18 @@ func (d *Cloud189) GetDetails(ctx context.Context) (*model.StorageDetails, error
}, nil
}

func (d *Cloud189) Transfer(ctx context.Context, dst model.Obj, shareURL, validCode string) error {
sharecode := d.extractCode(shareURL)
if sharecode == "" {
return fmt.Errorf("need share code")
}

shareid, err := d.getSharedID(sharecode)
if err != nil {
return err
}

return d.transfer(dst, shareid)
}

var _ driver.Driver = (*Cloud189)(nil)
2 changes: 1 addition & 1 deletion drivers/189/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
)

func random() string {
return fmt.Sprintf("0.%17v", myrand.Rand.Int63n(100000000000000000))
return fmt.Sprintf("0.%017d", myrand.Rand.Int63n(1e17))
}

func RsaEncode(origData []byte, j_rsakey string, hex bool) string {
Expand Down
8 changes: 8 additions & 0 deletions drivers/189/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,11 @@ type CapacityResp struct {
} `json:"familyCapacityInfo"`
TotalSize uint64 `json:"totalSize"`
}

type GetSharedInfoResp struct {
ResCode int `json:"res_code"`
ResMessage string `json:"res_message"`
AccessCode string `json:"accessCode"`
ShareID int64 `json:"shareId"`
ExpireTime int64 `json:"expireTime"`
}
52 changes: 52 additions & 0 deletions drivers/189/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"io"
"math"
"net/http"
"net/url"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -406,3 +407,54 @@ func (d *Cloud189) getCapacityInfo(ctx context.Context) (*CapacityResp, error) {
}
return &resp, nil
}

func (d *Cloud189) getSharedID(code string) (int64, error) {
resp := GetSharedInfoResp{}
_, err := d.request("https://cloud.189.cn/api/open/share/getShareInfoByCodeV2.action", http.MethodGet, func(req *resty.Request) {
req.SetHeader("Accept", "application/json;charset=UTF-8")
req.SetQueryParams(map[string]string{
"code": code,
})
}, &resp)
if err != nil {
return 0, err
}
if resp.ResCode != 0 || resp.ResMessage != "成功" {
return 0, errors.New(resp.ResMessage)
}
return resp.ShareID, nil
}

func (d *Cloud189) extractCode(str string) string {
u, err := url.Parse(str)
if err != nil {
fmt.Println("invalid share url")
return ""
}
return u.Query().Get("code")
}

func (d *Cloud189) transfer(dstDir model.Obj, shareID int64) error {
taskInfos := []base.Json{
{
"fileId": dstDir.GetID(),
"fileName": dstDir.GetName(),
"isFolder": 1,
},
}

if !dstDir.IsDir() {
return fmt.Errorf("it should be in the folder")
}
taskInfosBytes, err := utils.Json.Marshal(taskInfos)
form := map[string]string{
"type": "SHARE_SAVE",
"targetFolderId": dstDir.GetID(),
"taskInfos": string(taskInfosBytes),
"shareId": fmt.Sprintf("%d", shareID),
}
_, err = d.request("https://cloud.189.cn/api/open/batch/createBatchTask.action", http.MethodPost, func(req *resty.Request) {
req.SetFormData(form)
}, nil)
return err
}
54 changes: 54 additions & 0 deletions drivers/189pc/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -428,3 +428,57 @@ func (y *Cloud189PC) GetDetails(ctx context.Context) (*model.StorageDetails, err
DiskUsage: driver.DiskUsageFromUsedAndTotal(used, total),
}, nil
}

func (y *Cloud189PC) Transfer(ctx context.Context, dst model.Obj, shareURL, validCode string) error {
sharecode := y.extractCode(shareURL)
if sharecode == "" {
return fmt.Errorf("need share code")
}
shareid, fileid, filename, err := y.getSharedInfo(sharecode)
if err != nil {
return err
}
if shareid == -1 {
return fmt.Errorf("failed get share id")
}

taskInfos := []base.Json{
{
"fileId": fileid,
"fileName": filename,
"isFolder": 1,
},
}

if !dst.IsDir() {
return fmt.Errorf("it should be in the folder")
}
taskInfosBytes, err := utils.Json.Marshal(taskInfos)
if err != nil {
return err
}

form := map[string]string{
"targetFolderId": dst.GetID(),
"taskInfos": string(taskInfosBytes),
"shareId": fmt.Sprintf("%d", shareid),
}

resp, err := y.CreateBatchTask("SHARE_SAVE", y.FamilyID, dst.GetID(), form)

for {
state, err := y.CheckBatchTask("SHARE_SAVE", resp.TaskID)
if err != nil {
return err
}
switch state.TaskStatus {
case 4:
if state.FailedCount == 0 {
return nil
} else {
return fmt.Errorf("transfer failed")
}
}
time.Sleep(time.Millisecond * 400)
}
}
4 changes: 4 additions & 0 deletions drivers/189pc/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ import (
"github.com/OpenListTeam/OpenList/v4/pkg/utils/random"
)

func random_num() string {
return fmt.Sprintf("0.%017d", random.Rand.Int63n(1e17))
}

func clientSuffix() map[string]string {
rand := random.Rand
return map[string]string{
Expand Down
15 changes: 14 additions & 1 deletion drivers/189pc/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,9 @@ func (f *OldCommitUploadFileResp) toFile() *Cloud189File {
}

type CreateBatchTaskResp struct {
TaskID string `json:"taskId"`
ResCode int `json:"res_code"`
TaskID string `json:"taskId"`
ResMessage string `json:"res_message"`
}

type BatchTaskStateResp struct {
Expand All @@ -371,6 +373,7 @@ type BatchTaskStateResp struct {
SuccessedCount int `json:"successedCount"`
SuccessedFileIDList []int64 `json:"successedFileIdList"`
TaskID string `json:"taskId"`
ResMessage string `json:"res_message"`
TaskStatus int `json:"taskStatus"` //1 初始化 2 存在冲突 3 执行中,4 完成
}

Expand Down Expand Up @@ -427,3 +430,13 @@ type CapacityResp struct {
} `json:"familyCapacityInfo"`
TotalSize uint64 `json:"totalSize"`
}

type GetSharedInfoResp struct {
ResCode int `json:"res_code"`
ResMessage string `json:"res_message"`
AccessCode string `json:"accessCode"`
ShareID int64 `json:"shareId"`
ExpireTime int64 `json:"expireTime"`
FileName string `json:"fileName"`
FileId string `json:"fileId"`
}
48 changes: 48 additions & 0 deletions drivers/189pc/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -1483,3 +1483,51 @@ func (y *Cloud189PC) getCapacityInfo(ctx context.Context) (*CapacityResp, error)
}
return &resp, nil
}

func (y *Cloud189PC) getSharedInfo(code string) (int64, string, string, error) {
resp := GetSharedInfoResp{}
sessionKey := y.getTokenInfo().SessionKey
if sessionKey == "" {
if err := y.refreshSession(); err != nil {
return -1, "", "", err
}
}
req := y.getClient().R().
SetHeader("Accept", "application/json;charset=UTF-8").
SetHeader("Referer", fmt.Sprintf("https://cloud.189.cn/web/share?code=%s", code)).
SetHeader("SessionKey", y.getTokenInfo().SessionKey).
SetQueryParams(map[string]string{
"noCache": random_num(),
"shareCode": code,
})
req.SetResult(&resp)
res, err := req.Execute(http.MethodGet, "https://cloud.189.cn/api/open/share/getShareInfoByCodeV2.action")

if strings.Contains(res.String(), "userSessionBO is null") {
if err = y.refreshSession(); err != nil {
return -1, "", "", err
}
return y.getSharedInfo(code)
}

if strings.Contains(res.String(), "InvalidSessionKey") {
if err = y.refreshSession(); err != nil {
return -1, "", "", err
}
return y.getSharedInfo(code)
}

if resp.ResCode != 0 || resp.ResMessage != "成功" {
return -1, "", "", errors.New(resp.ResMessage)
}
return resp.ShareID, resp.FileId, resp.FileName, nil
}

func (y *Cloud189PC) extractCode(str string) string {
u, err := url.Parse(str)
if err != nil {
fmt.Println("invalid share url")
return ""
}
return u.Query().Get("code")
}
42 changes: 42 additions & 0 deletions drivers/aliyundrive/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,4 +368,46 @@ func (d *AliDrive) Other(ctx context.Context, args model.OtherArgs) (interface{}
return resp, nil
}

func (d *AliDrive) Transfer(ctx context.Context, dst model.Obj, shareURL, validCode string) error {
shareid := d.extractShareId(shareURL)
if shareid == "" {
return fmt.Errorf("invalid share url")
}
shareToken, err := d.getShareToken(shareid, validCode)
if err != nil {
return err
}
fileid, parent_fileid := d.getFileId(shareid, shareToken)
res, err, _ := d.request("https://api.aliyundrive.com/adrive/v4/batch", http.MethodPost, func(req *resty.Request) {
req.SetBody(base.Json{
"requests": []base.Json{
{
"headers": base.Json{
"Content-Type": "application/json",
},
"method": "POST",
"id": "0",
"body": base.Json{
"share_id": shareid,
"file_id": fileid,
"to_drive_id": dst.GetID(),
"to_parent_file_id": parent_fileid,
},
"url": "/file/copy",
},
},
"resource": "file",
})
req.SetHeader("X-Share-Token", shareToken)
}, nil)
if err != nil {
return err
}
status := utils.Json.Get(res, "responses", 0, "status").ToInt()
if status < 300 && status >= 100 {
return nil
}
return fmt.Errorf("transfer failed: %s", string(res))
}

var _ driver.Driver = (*AliDrive)(nil)
9 changes: 9 additions & 0 deletions drivers/aliyundrive/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,12 @@ type UploadResp struct {

RapidUpload bool `json:"rapid_upload"`
}

type SharedTokenResp struct {
ShareToken string `json:"share_token"`
}

type ShareInfoResp struct {
FileId string `json:"file_id"`
ParentFileId string `json:"parent_file_id"`
}
46 changes: 46 additions & 0 deletions drivers/aliyundrive/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"net/http"
"regexp"

"github.com/OpenListTeam/OpenList/v4/drivers/base"
"github.com/OpenListTeam/OpenList/v4/internal/op"
Expand Down Expand Up @@ -202,3 +203,48 @@ func (d *AliDrive) batch(srcId, dstId string, url string) error {
}
return errors.New(string(res))
}

func (d *AliDrive) getShareToken(shareid, share_pwd string) (string, error) {
resp := SharedTokenResp{}
_, err, _ := d.request("https://api.aliyundrive.com/v2/share_link/get_share_token", http.MethodPost, func(req *resty.Request) {
req.SetBody(base.Json{
"share_id": shareid,
"share_pwd": share_pwd,
})
}, resp)
if err != nil {
return "", err
}
return resp.ShareToken, nil
}

func (d *AliDrive) getFileId(shareid, token string) (string, string) {
resp := ShareInfoResp{}
_, err, _ := d.request("https://api.aliyundrive.com/adrive/v2/file/list_by_share", http.MethodPost, func(req *resty.Request) {
req.SetHeader("x-share-token", token)
req.SetBody(base.Json{
"share_id": shareid,
"order_by": "name",
"order_direction": "DESC",
"limit": 20,
"parent_file_id": "root",
"image_thumbnail_process": "image/resize,w_256/format,jpeg",
"image_url_process": "image/resize,w_1920/format,jpeg/interlace,1",
"video_thumbnail_process": "video/snapshot,t_1000,f_jpg,ar_auto,w_256",
})
}, &resp)
if err != nil {
return "", ""
}
return resp.FileId, resp.ParentFileId
}

func (d *AliDrive) extractShareId(shareUrl string) string {
// https://www.alipan.com/s/XVDFP7mpuZK
re := regexp.MustCompile(`https?://(?:[a-zA-Z0-9-]+\.)*alipan\.com(?:\:\d+)?/s/([a-zA-Z0-9_-]+)`)
matches := re.FindStringSubmatch(shareUrl)
if len(matches) >= 2 {
return matches[1]
}
return ""
}
Loading