mirror of https://github.com/Xhofe/alist
parent
fbf3fb825b
commit
1c8d895fc0
|
@ -27,6 +27,7 @@ import (
|
||||||
_ "github.com/alist-org/alist/v3/drivers/sftp"
|
_ "github.com/alist-org/alist/v3/drivers/sftp"
|
||||||
_ "github.com/alist-org/alist/v3/drivers/smb"
|
_ "github.com/alist-org/alist/v3/drivers/smb"
|
||||||
_ "github.com/alist-org/alist/v3/drivers/teambition"
|
_ "github.com/alist-org/alist/v3/drivers/teambition"
|
||||||
|
_ "github.com/alist-org/alist/v3/drivers/terabox"
|
||||||
_ "github.com/alist-org/alist/v3/drivers/thunder"
|
_ "github.com/alist-org/alist/v3/drivers/thunder"
|
||||||
_ "github.com/alist-org/alist/v3/drivers/uss"
|
_ "github.com/alist-org/alist/v3/drivers/uss"
|
||||||
_ "github.com/alist-org/alist/v3/drivers/virtual"
|
_ "github.com/alist-org/alist/v3/drivers/virtual"
|
||||||
|
|
|
@ -0,0 +1,214 @@
|
||||||
|
package terbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"crypto/md5"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"github.com/alist-org/alist/v3/drivers/base"
|
||||||
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"io"
|
||||||
|
"math"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
stdpath "path"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Terabox struct {
|
||||||
|
model.Storage
|
||||||
|
Addition
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) Config() driver.Config {
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) GetAddition() driver.Additional {
|
||||||
|
return &d.Addition
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) Init(ctx context.Context) error {
|
||||||
|
_, err := d.request("https://www.terabox.com/api/check/login", http.MethodGet, nil, nil)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) Drop(ctx context.Context) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
||||||
|
files, err := d.getFiles(dir.GetPath())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return utils.SliceConvert(files, func(src File) (model.Obj, error) {
|
||||||
|
return fileToObj(src), nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
|
if d.DownloadAPI == "crack" {
|
||||||
|
return d.linkCrack(file, args)
|
||||||
|
}
|
||||||
|
return d.linkOfficial(file, args)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
|
||||||
|
_, err := d.create(stdpath.Join(parentDir.GetPath(), dirName), 0, 1, "", "")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||||
|
data := []base.Json{
|
||||||
|
{
|
||||||
|
"path": srcObj.GetPath(),
|
||||||
|
"dest": dstDir.GetPath(),
|
||||||
|
"newname": srcObj.GetName(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err := d.manage("move", data)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
|
||||||
|
data := []base.Json{
|
||||||
|
{
|
||||||
|
"path": srcObj.GetPath(),
|
||||||
|
"newname": newName,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err := d.manage("rename", data)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||||
|
data := []base.Json{
|
||||||
|
{
|
||||||
|
"path": srcObj.GetPath(),
|
||||||
|
"dest": dstDir.GetPath(),
|
||||||
|
"newname": srcObj.GetName(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err := d.manage("copy", data)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) Remove(ctx context.Context, obj model.Obj) error {
|
||||||
|
data := []string{obj.GetPath()}
|
||||||
|
_, err := d.manage("delete", data)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
||||||
|
tempFile, err := utils.CreateTempFile(stream.GetReadCloser())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
_ = tempFile.Close()
|
||||||
|
_ = os.Remove(tempFile.Name())
|
||||||
|
}()
|
||||||
|
var Default int64 = 4 * 1024 * 1024
|
||||||
|
defaultByteData := make([]byte, Default)
|
||||||
|
count := int(math.Ceil(float64(stream.GetSize()) / float64(Default)))
|
||||||
|
// cal md5
|
||||||
|
h1 := md5.New()
|
||||||
|
h2 := md5.New()
|
||||||
|
block_list := make([]string, 0)
|
||||||
|
left := stream.GetSize()
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
byteSize := Default
|
||||||
|
var byteData []byte
|
||||||
|
if left < Default {
|
||||||
|
byteSize = left
|
||||||
|
byteData = make([]byte, byteSize)
|
||||||
|
} else {
|
||||||
|
byteData = defaultByteData
|
||||||
|
}
|
||||||
|
left -= byteSize
|
||||||
|
_, err = io.ReadFull(tempFile, byteData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
h1.Write(byteData)
|
||||||
|
h2.Write(byteData)
|
||||||
|
block_list = append(block_list, fmt.Sprintf("\"%s\"", hex.EncodeToString(h2.Sum(nil))))
|
||||||
|
h2.Reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = tempFile.Seek(0, io.SeekStart)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
rawPath := stdpath.Join(dstDir.GetPath(), stream.GetName())
|
||||||
|
path := encodeURIComponent(rawPath)
|
||||||
|
block_list_str := fmt.Sprintf("[%s]", strings.Join(block_list, ","))
|
||||||
|
data := fmt.Sprintf("path=%s&size=%d&isdir=0&autoinit=1&block_list=%s",
|
||||||
|
path, stream.GetSize(),
|
||||||
|
block_list_str)
|
||||||
|
params := map[string]string{}
|
||||||
|
var precreateResp PrecreateResp
|
||||||
|
_, err = d.post("/api/precreate", params, data, &precreateResp)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Debugf("%+v", precreateResp)
|
||||||
|
if precreateResp.ReturnType == 2 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
params = map[string]string{
|
||||||
|
"method": "upload",
|
||||||
|
"path": path,
|
||||||
|
"uploadid": precreateResp.Uploadid,
|
||||||
|
"app_id": "250528",
|
||||||
|
"web": "1",
|
||||||
|
"channel": "dubox",
|
||||||
|
"clienttype": "0",
|
||||||
|
}
|
||||||
|
left = stream.GetSize()
|
||||||
|
for i, partseq := range precreateResp.BlockList {
|
||||||
|
if utils.IsCanceled(ctx) {
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
|
byteSize := Default
|
||||||
|
var byteData []byte
|
||||||
|
if left < Default {
|
||||||
|
byteSize = left
|
||||||
|
byteData = make([]byte, byteSize)
|
||||||
|
} else {
|
||||||
|
byteData = defaultByteData
|
||||||
|
}
|
||||||
|
left -= byteSize
|
||||||
|
_, err = io.ReadFull(tempFile, byteData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
u := "https://c-jp.terabox.com/rest/2.0/pcs/superfile2"
|
||||||
|
params["partseq"] = strconv.Itoa(partseq)
|
||||||
|
res, err := base.RestyClient.R().
|
||||||
|
SetContext(ctx).
|
||||||
|
SetQueryParams(params).
|
||||||
|
SetFileReader("file", stream.GetName(), bytes.NewReader(byteData)).
|
||||||
|
SetHeader("Cookie", d.Cookie).
|
||||||
|
Post(u)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Debugln(res.String())
|
||||||
|
if len(precreateResp.BlockList) > 0 {
|
||||||
|
up(i * 100 / len(precreateResp.BlockList))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, err = d.create(rawPath, stream.GetSize(), 0, precreateResp.Uploadid, block_list_str)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ driver.Driver = (*Terabox)(nil)
|
|
@ -0,0 +1,25 @@
|
||||||
|
package terbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
|
"github.com/alist-org/alist/v3/internal/op"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Addition struct {
|
||||||
|
driver.RootPath
|
||||||
|
Cookie string `json:"cookie" required:"true"`
|
||||||
|
DownloadAPI string `json:"download_api" type:"select" options:"official,crack" default:"official"`
|
||||||
|
OrderBy string `json:"order_by" type:"select" options:"name,time,size" default:"name"`
|
||||||
|
OrderDirection string `json:"order_direction" type:"select" options:"asc,desc" default:"asc"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = driver.Config{
|
||||||
|
Name: "Terabox",
|
||||||
|
DefaultRoot: "/",
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
op.RegisterDriver(func() driver.Driver {
|
||||||
|
return &Terabox{}
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
package terbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type File struct {
|
||||||
|
//TkbindId int `json:"tkbind_id"`
|
||||||
|
//OwnerType int `json:"owner_type"`
|
||||||
|
//Category int `json:"category"`
|
||||||
|
//RealCategory string `json:"real_category"`
|
||||||
|
FsId int64 `json:"fs_id"`
|
||||||
|
ServerMtime int64 `json:"server_mtime"`
|
||||||
|
//OperId int `json:"oper_id"`
|
||||||
|
//ServerCtime int `json:"server_ctime"`
|
||||||
|
Thumbs struct {
|
||||||
|
//Icon string `json:"icon"`
|
||||||
|
Url3 string `json:"url3"`
|
||||||
|
//Url2 string `json:"url2"`
|
||||||
|
//Url1 string `json:"url1"`
|
||||||
|
} `json:"thumbs"`
|
||||||
|
//Wpfile int `json:"wpfile"`
|
||||||
|
//LocalMtime int `json:"local_mtime"`
|
||||||
|
Size int64 `json:"size"`
|
||||||
|
//ExtentTinyint7 int `json:"extent_tinyint7"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
//Share int `json:"share"`
|
||||||
|
//ServerAtime int `json:"server_atime"`
|
||||||
|
//Pl int `json:"pl"`
|
||||||
|
//LocalCtime int `json:"local_ctime"`
|
||||||
|
ServerFilename string `json:"server_filename"`
|
||||||
|
//Md5 string `json:"md5"`
|
||||||
|
//OwnerId int `json:"owner_id"`
|
||||||
|
//Unlist int `json:"unlist"`
|
||||||
|
Isdir int `json:"isdir"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListResp struct {
|
||||||
|
Errno int `json:"errno"`
|
||||||
|
GuidInfo string `json:"guid_info"`
|
||||||
|
List []File `json:"list"`
|
||||||
|
RequestId int64 `json:"request_id"`
|
||||||
|
Guid int `json:"guid"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func fileToObj(f File) *model.ObjThumb {
|
||||||
|
return &model.ObjThumb{
|
||||||
|
Object: model.Object{
|
||||||
|
ID: strconv.FormatInt(f.FsId, 10),
|
||||||
|
Name: f.ServerFilename,
|
||||||
|
Size: f.Size,
|
||||||
|
Modified: time.Unix(f.ServerMtime, 0),
|
||||||
|
IsFolder: f.Isdir == 1,
|
||||||
|
},
|
||||||
|
Thumbnail: model.Thumbnail{Thumbnail: f.Thumbs.Url3},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type DownloadResp struct {
|
||||||
|
Errno int `json:"errno"`
|
||||||
|
Dlink []struct {
|
||||||
|
Dlink string `json:"dlink"`
|
||||||
|
} `json:"dlink"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DownloadResp2 struct {
|
||||||
|
Errno int `json:"errno"`
|
||||||
|
Info []struct {
|
||||||
|
Dlink string `json:"dlink"`
|
||||||
|
} `json:"info"`
|
||||||
|
RequestID int64 `json:"request_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type HomeInfoResp struct {
|
||||||
|
Errno int `json:"errno"`
|
||||||
|
Data struct {
|
||||||
|
Sign1 string `json:"sign1"`
|
||||||
|
Sign3 string `json:"sign3"`
|
||||||
|
Timestamp int `json:"timestamp"`
|
||||||
|
} `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PrecreateResp struct {
|
||||||
|
Path string `json:"path"`
|
||||||
|
Uploadid string `json:"uploadid"`
|
||||||
|
ReturnType int `json:"return_type"`
|
||||||
|
BlockList []int `json:"block_list"`
|
||||||
|
Errno int `json:"errno"`
|
||||||
|
RequestId int64 `json:"request_id"`
|
||||||
|
}
|
|
@ -0,0 +1,192 @@
|
||||||
|
package terbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
|
"github.com/alist-org/alist/v3/drivers/base"
|
||||||
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
|
"github.com/go-resty/resty/v2"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (d *Terabox) request(furl string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
||||||
|
req := base.RestyClient.R()
|
||||||
|
req.SetHeaders(map[string]string{
|
||||||
|
"Cookie": d.Cookie,
|
||||||
|
"Accept": "application/json, text/plain, */*",
|
||||||
|
"Referer": "https://www.terabox.com/",
|
||||||
|
"User-Agent": base.UserAgent,
|
||||||
|
})
|
||||||
|
req.SetQueryParam("app_id", "250528")
|
||||||
|
req.SetQueryParam("web", "1")
|
||||||
|
req.SetQueryParam("channel", "dubox")
|
||||||
|
req.SetQueryParam("clienttype", "0")
|
||||||
|
if callback != nil {
|
||||||
|
callback(req)
|
||||||
|
}
|
||||||
|
if resp != nil {
|
||||||
|
req.SetResult(resp)
|
||||||
|
}
|
||||||
|
res, err := req.Execute(method, furl)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return res.Body(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) get(pathname string, params map[string]string, resp interface{}) ([]byte, error) {
|
||||||
|
return d.request("https://www.terabox.com"+pathname, http.MethodGet, func(req *resty.Request) {
|
||||||
|
req.SetQueryParams(params)
|
||||||
|
}, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) post(pathname string, params map[string]string, data interface{}, resp interface{}) ([]byte, error) {
|
||||||
|
return d.request("https://www.terabox.com"+pathname, http.MethodPost, func(req *resty.Request) {
|
||||||
|
req.SetQueryParams(params)
|
||||||
|
req.SetBody(data)
|
||||||
|
}, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) getFiles(dir string) ([]File, error) {
|
||||||
|
page := 1
|
||||||
|
num := 100
|
||||||
|
params := map[string]string{
|
||||||
|
"dir": dir,
|
||||||
|
}
|
||||||
|
if d.OrderBy != "" {
|
||||||
|
params["order"] = d.OrderBy
|
||||||
|
if d.OrderDirection == "desc" {
|
||||||
|
params["desc"] = "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res := make([]File, 0)
|
||||||
|
for {
|
||||||
|
params["page"] = strconv.Itoa(page)
|
||||||
|
params["num"] = strconv.Itoa(num)
|
||||||
|
var resp ListResp
|
||||||
|
_, err := d.get("/api/list", params, &resp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(resp.List) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
res = append(res, resp.List...)
|
||||||
|
page++
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func sign(s1, s2 string) string {
|
||||||
|
var a = make([]int, 256)
|
||||||
|
var p = make([]int, 256)
|
||||||
|
var o []byte
|
||||||
|
var v = len(s1)
|
||||||
|
for q := 0; q < 256; q++ {
|
||||||
|
a[q] = int(s1[(q % v) : (q%v)+1][0])
|
||||||
|
p[q] = q
|
||||||
|
}
|
||||||
|
for u, q := 0, 0; q < 256; q++ {
|
||||||
|
u = (u + p[q] + a[q]) % 256
|
||||||
|
p[q], p[u] = p[u], p[q]
|
||||||
|
}
|
||||||
|
for i, u, q := 0, 0, 0; q < len(s2); q++ {
|
||||||
|
i = (i + 1) % 256
|
||||||
|
u = (u + p[i]) % 256
|
||||||
|
p[i], p[u] = p[u], p[i]
|
||||||
|
k := p[((p[i] + p[u]) % 256)]
|
||||||
|
o = append(o, byte(int(s2[q])^k))
|
||||||
|
}
|
||||||
|
return base64.StdEncoding.EncodeToString(o)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) genSign() (string, error) {
|
||||||
|
var resp HomeInfoResp
|
||||||
|
_, err := d.get("/api/home/info", map[string]string{}, &resp)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return sign(resp.Data.Sign3, resp.Data.Sign1), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) linkOfficial(file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
|
var resp DownloadResp
|
||||||
|
signString, err := d.genSign()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
params := map[string]string{
|
||||||
|
"type": "dlink",
|
||||||
|
"fidlist": fmt.Sprintf("[%s]", file.GetID()),
|
||||||
|
"sign": signString,
|
||||||
|
"vip": "2",
|
||||||
|
"timestamp": strconv.FormatInt(time.Now().Unix(), 10),
|
||||||
|
}
|
||||||
|
_, err = d.get("/api/download", params, &resp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res, err := base.NoRedirectClient.R().SetHeader("Cookie", d.Cookie).SetHeader("User-Agent", base.UserAgent).Get(resp.Dlink[0].Dlink)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
u := res.Header().Get("location")
|
||||||
|
return &model.Link{
|
||||||
|
URL: u,
|
||||||
|
Header: http.Header{
|
||||||
|
"User-Agent": []string{base.UserAgent},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) linkCrack(file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
|
var resp DownloadResp2
|
||||||
|
param := map[string]string{
|
||||||
|
"target": fmt.Sprintf("[\"%s\"]", file.GetPath()),
|
||||||
|
"dlink": "1",
|
||||||
|
"origin": "dlna",
|
||||||
|
}
|
||||||
|
_, err := d.get("/api/filemetas", param, &resp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &model.Link{
|
||||||
|
URL: resp.Info[0].Dlink,
|
||||||
|
Header: http.Header{
|
||||||
|
"User-Agent": []string{base.UserAgent},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) manage(opera string, filelist interface{}) ([]byte, error) {
|
||||||
|
params := map[string]string{
|
||||||
|
"onnest": "fail",
|
||||||
|
"opera": opera,
|
||||||
|
}
|
||||||
|
marshal, err := utils.Json.Marshal(filelist)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
data := fmt.Sprintf("async=0&filelist=%s&ondup=newcopy", string(marshal))
|
||||||
|
return d.post("/api/filemanager", params, data, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) create(path string, size int64, isdir int, uploadid, block_list string) ([]byte, error) {
|
||||||
|
params := map[string]string{}
|
||||||
|
data := fmt.Sprintf("path=%s&size=%d&isdir=%d", encodeURIComponent(path), size, isdir)
|
||||||
|
if uploadid != "" {
|
||||||
|
data += fmt.Sprintf("&uploadid=%s&block_list=%s", uploadid, block_list)
|
||||||
|
}
|
||||||
|
return d.post("/api/create", params, data, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeURIComponent(str string) string {
|
||||||
|
r := url.QueryEscape(str)
|
||||||
|
r = strings.ReplaceAll(r, "+", "%20")
|
||||||
|
return r
|
||||||
|
}
|
Loading…
Reference in New Issue