mirror of https://github.com/Xhofe/alist
				
				
				
			🚧 123pan write
							parent
							
								
									a7e9bb9e9a
								
							
						
					
					
						commit
						fe79f9518b
					
				| 
						 | 
				
			
			@ -1,12 +1,17 @@
 | 
			
		|||
package _23
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/hmac"
 | 
			
		||||
	"crypto/sha256"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"github.com/Xhofe/alist/conf"
 | 
			
		||||
	"github.com/Xhofe/alist/drivers/base"
 | 
			
		||||
	"github.com/Xhofe/alist/model"
 | 
			
		||||
	"github.com/Xhofe/alist/utils"
 | 
			
		||||
	"github.com/go-resty/resty/v2"
 | 
			
		||||
	jsoniter "github.com/json-iterator/go"
 | 
			
		||||
	"math/rand"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"time"
 | 
			
		||||
| 
						 | 
				
			
			@ -122,6 +127,20 @@ func (driver Pan123) GetFiles(parentId string, account *model.Account) ([]Pan123
 | 
			
		|||
	return res, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (driver Pan123) Post(url string, data base.Json, account *model.Account) ([]byte, error) {
 | 
			
		||||
	res, err := pan123Client.R().
 | 
			
		||||
		SetHeader("authorization", "Bearer "+account.AccessToken).
 | 
			
		||||
		SetBody(data).Post(url)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	body := res.Body()
 | 
			
		||||
	if jsoniter.Get(body, "code").ToInt() != 0 {
 | 
			
		||||
		return nil, errors.New(jsoniter.Get(body, "message").ToString())
 | 
			
		||||
	}
 | 
			
		||||
	return body, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (driver Pan123) GetFile(path string, account *model.Account) (*Pan123File, error) {
 | 
			
		||||
	dir, name := filepath.Split(path)
 | 
			
		||||
	dir = utils.ParsePath(dir)
 | 
			
		||||
| 
						 | 
				
			
			@ -143,6 +162,28 @@ func (driver Pan123) GetFile(path string, account *model.Account) (*Pan123File,
 | 
			
		|||
	return nil, base.ErrPathNotFound
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func RandStr(length int) string {
 | 
			
		||||
	str := "123456789abcdefghijklmnopqrstuvwxyz"
 | 
			
		||||
	bytes := []byte(str)
 | 
			
		||||
	var result []byte
 | 
			
		||||
	rand.Seed(time.Now().UnixNano()+ int64(rand.Intn(100)))
 | 
			
		||||
	for i := 0; i < length; i++ {
 | 
			
		||||
		result = append(result, bytes[rand.Intn(len(bytes))])
 | 
			
		||||
	}
 | 
			
		||||
	return string(result)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func HMAC(message string, secret string) string {
 | 
			
		||||
	key := []byte(secret)
 | 
			
		||||
	h := hmac.New(sha256.New, key)
 | 
			
		||||
	h.Write([]byte(message))
 | 
			
		||||
	//	fmt.Println(h.Sum(nil))
 | 
			
		||||
	//sha := hex.EncodeToString(h.Sum(nil))
 | 
			
		||||
	//	fmt.Println(sha)
 | 
			
		||||
	//return sha
 | 
			
		||||
	return string(h.Sum(nil))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	base.RegisterDriver(&Pan123{})
 | 
			
		||||
	pan123Client.SetRetryCount(3)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,15 +1,21 @@
 | 
			
		|||
package _23
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/hex"
 | 
			
		||||
	"encoding/xml"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"github.com/Xhofe/alist/conf"
 | 
			
		||||
	"github.com/Xhofe/alist/drivers/base"
 | 
			
		||||
	"github.com/Xhofe/alist/model"
 | 
			
		||||
	"github.com/Xhofe/alist/utils"
 | 
			
		||||
	"github.com/gin-gonic/gin"
 | 
			
		||||
	jsoniter "github.com/json-iterator/go"
 | 
			
		||||
	log "github.com/sirupsen/logrus"
 | 
			
		||||
	url "net/url"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Pan123 struct{}
 | 
			
		||||
| 
						 | 
				
			
			@ -161,7 +167,7 @@ func (driver Pan123) Link(path string, account *model.Account) (*base.Link, erro
 | 
			
		|||
	link := base.Link{}
 | 
			
		||||
	if res.StatusCode() == 302 {
 | 
			
		||||
		link.Url = res.Header().Get("location")
 | 
			
		||||
	}else {
 | 
			
		||||
	} else {
 | 
			
		||||
		link.Url = resp.Data.DownloadUrl
 | 
			
		||||
	}
 | 
			
		||||
	return &link, nil
 | 
			
		||||
| 
						 | 
				
			
			@ -198,22 +204,145 @@ func (driver Pan123) Preview(path string, account *model.Account) (interface{},
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (driver Pan123) MakeDir(path string, account *model.Account) error {
 | 
			
		||||
	return base.ErrNotImplement
 | 
			
		||||
	dir, name := filepath.Split(path)
 | 
			
		||||
	parentFile, err := driver.File(dir, account)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if !parentFile.IsDir() {
 | 
			
		||||
		return base.ErrNotFolder
 | 
			
		||||
	}
 | 
			
		||||
	parentFileId, _ := strconv.Atoi(parentFile.Id)
 | 
			
		||||
	data := base.Json{
 | 
			
		||||
		"driveId":      0,
 | 
			
		||||
		"etag":         "",
 | 
			
		||||
		"fileName":     name,
 | 
			
		||||
		"parentFileId": parentFileId,
 | 
			
		||||
		"size":         0,
 | 
			
		||||
		"type":         1,
 | 
			
		||||
	}
 | 
			
		||||
	_, err = driver.Post("https://www.123pan.com/api/file/upload_request", data, account)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		_ = base.DeleteCache(dir, account)
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (driver Pan123) Move(src string, dst string, account *model.Account) error {
 | 
			
		||||
	return base.ErrNotImplement
 | 
			
		||||
	srcDir, _ := filepath.Split(src)
 | 
			
		||||
	dstDir, dstName := filepath.Split(dst)
 | 
			
		||||
	srcFile, err := driver.File(src, account)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	fileId, _ := strconv.Atoi(srcFile.Id)
 | 
			
		||||
	// rename
 | 
			
		||||
	if srcDir == dstDir {
 | 
			
		||||
		data := base.Json{
 | 
			
		||||
			"driveId":  0,
 | 
			
		||||
			"fileId":   fileId,
 | 
			
		||||
			"fileName": dstName,
 | 
			
		||||
		}
 | 
			
		||||
		_, err = driver.Post("https://www.123pan.com/api/file/rename", data, account)
 | 
			
		||||
	} else {
 | 
			
		||||
		// move
 | 
			
		||||
		dstDirFile, err := driver.File(dstDir, account)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		parentFileId, _ := strconv.Atoi(dstDirFile.Id)
 | 
			
		||||
		data := base.Json{
 | 
			
		||||
			"fileId":       fileId,
 | 
			
		||||
			"parentFileId": parentFileId,
 | 
			
		||||
		}
 | 
			
		||||
		_, err = driver.Post("https://www.123pan.com/api/file/mod_pid", data, account)
 | 
			
		||||
	}
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		_ = base.DeleteCache(srcDir, account)
 | 
			
		||||
		_ = base.DeleteCache(dstDir, account)
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (driver Pan123) Copy(src string, dst string, account *model.Account) error {
 | 
			
		||||
	return base.ErrNotImplement
 | 
			
		||||
	return base.ErrNotSupport
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (driver Pan123) Delete(path string, account *model.Account) error {
 | 
			
		||||
	return base.ErrNotImplement
 | 
			
		||||
	file, err := driver.GetFile(path, account)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	data := base.Json{
 | 
			
		||||
		"driveId":           0,
 | 
			
		||||
		"operation":         true,
 | 
			
		||||
		"fileTrashInfoList": file,
 | 
			
		||||
	}
 | 
			
		||||
	_, err = driver.Post("https://www.123pan.com/api/file/trash", data, account)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		_ = base.DeleteCache(utils.Dir(path), account)
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type UploadResp struct {
 | 
			
		||||
	XMLName  xml.Name `xml:"InitiateMultipartUploadResult"`
 | 
			
		||||
	Bucket   string   `xml:"Bucket"`
 | 
			
		||||
	Key      string   `xml:"Key"`
 | 
			
		||||
	UploadId string   `xml:"UploadId"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO unfinished
 | 
			
		||||
func (driver Pan123) Upload(file *model.FileStream, account *model.Account) error {
 | 
			
		||||
	parentFile, err := driver.File(file.ParentPath, account)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if !parentFile.IsDir() {
 | 
			
		||||
		return base.ErrNotFolder
 | 
			
		||||
	}
 | 
			
		||||
	parentFileId, _ := strconv.Atoi(parentFile.Id)
 | 
			
		||||
	data := base.Json{
 | 
			
		||||
		"driveId":      0,
 | 
			
		||||
		"duplicate":    true,
 | 
			
		||||
		"etag":         RandStr(32), //maybe file's md5
 | 
			
		||||
		"fileName":     file.GetFileName(),
 | 
			
		||||
		"parentFileId": parentFileId,
 | 
			
		||||
		"size":         file.GetSize(),
 | 
			
		||||
		"type":         0,
 | 
			
		||||
	}
 | 
			
		||||
	res, err := driver.Post("https://www.123pan.com/api/file/upload_request", data, account)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	baseUrl := fmt.Sprintf("https://file.123pan.com/%s/%s", jsoniter.Get(res, "data.Bucket").ToString(), jsoniter.Get(res, "data.Key").ToString())
 | 
			
		||||
	var resp UploadResp
 | 
			
		||||
	kSecret := jsoniter.Get(res, "data.SecretAccessKey").ToString()
 | 
			
		||||
	nowTimeStr := time.Now().String()
 | 
			
		||||
	Date := strings.ReplaceAll(strings.Split(nowTimeStr, "T")[0],"-","")
 | 
			
		||||
 | 
			
		||||
	StringToSign := fmt.Sprintf("%s\n%s\n%s\n%s",
 | 
			
		||||
		"AWS4-HMAC-SHA256",
 | 
			
		||||
		nowTimeStr,
 | 
			
		||||
		fmt.Sprintf("%s/us-east-1/s3/aws4_request", Date),
 | 
			
		||||
		)
 | 
			
		||||
 | 
			
		||||
	kDate := HMAC("AWS4"+kSecret, Date)
 | 
			
		||||
	kRegion := HMAC(kDate, "us-east-1")
 | 
			
		||||
	kService := HMAC(kRegion, "s3")
 | 
			
		||||
	kSigning := HMAC(kService, "aws4_request")
 | 
			
		||||
	_, err = pan123Client.R().SetResult(&resp).SetHeaders(map[string]string{
 | 
			
		||||
		"Authorization": fmt.Sprintf("AWS4-HMAC-SHA256 Credential=%s/%s/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-security-token;x-amz-user-agent, Signature=%s",
 | 
			
		||||
			jsoniter.Get(res, "data.AccessKeyId"),
 | 
			
		||||
			Date,
 | 
			
		||||
			hex.EncodeToString([]byte(HMAC(StringToSign, kSigning)))),
 | 
			
		||||
		"X-Amz-Content-Sha256": "UNSIGNED-PAYLOAD",
 | 
			
		||||
		"X-Amz-Date":           nowTimeStr,
 | 
			
		||||
		"x-amz-security-token": jsoniter.Get(res, "data.SessionToken").ToString(),
 | 
			
		||||
	}).Post(fmt.Sprintf("%s?uploads", baseUrl))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return base.ErrNotImplement
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue