fix(pikpak): hash calculation and fast upload judgment (#4745 fix #1081)

pull/4750/head v3.21.0
foxxorcat 2023-07-11 22:19:21 +08:00 committed by GitHub
parent 3f8b3da52b
commit a31af209cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 71 additions and 31 deletions

View File

@ -2,8 +2,6 @@ package pikpak
import ( import (
"context" "context"
"crypto/sha1"
"encoding/hex"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
@ -19,7 +17,6 @@ import (
"github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3/s3manager" "github.com/aws/aws-sdk-go/service/s3/s3manager"
"github.com/go-resty/resty/v2" "github.com/go-resty/resty/v2"
jsoniter "github.com/json-iterator/go"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
@ -135,9 +132,8 @@ func (d *PikPak) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
_ = tempFile.Close() _ = tempFile.Close()
_ = os.Remove(tempFile.Name()) _ = os.Remove(tempFile.Name())
}() }()
// cal sha1 // cal gcid
s := sha1.New() sha1Str, err := getGcid(tempFile, stream.GetSize())
_, err = io.Copy(s, tempFile)
if err != nil { if err != nil {
return err return err
} }
@ -145,8 +141,9 @@ func (d *PikPak) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
if err != nil { if err != nil {
return err return err
} }
sha1Str := hex.EncodeToString(s.Sum(nil)) var resp UploadTaskData
data := base.Json{ res, err := d.request("https://api-drive.mypikpak.com/drive/v1/files", http.MethodPost, func(req *resty.Request) {
req.SetBody(base.Json{
"kind": "drive#file", "kind": "drive#file",
"name": stream.GetName(), "name": stream.GetName(),
"size": stream.GetSize(), "size": stream.GetSize(),
@ -154,28 +151,23 @@ func (d *PikPak) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
"upload_type": "UPLOAD_TYPE_RESUMABLE", "upload_type": "UPLOAD_TYPE_RESUMABLE",
"objProvider": base.Json{"provider": "UPLOAD_TYPE_UNKNOWN"}, "objProvider": base.Json{"provider": "UPLOAD_TYPE_UNKNOWN"},
"parent_id": dstDir.GetID(), "parent_id": dstDir.GetID(),
} "folder_type": "NORMAL",
res, err := d.request("https://api-drive.mypikpak.com/drive/v1/files", http.MethodPost, func(req *resty.Request) { })
req.SetBody(data) }, &resp)
}, nil)
if err != nil { if err != nil {
return err return err
} }
if stream.GetSize() == 0 {
// 秒传成功
if resp.Resumable == nil {
log.Debugln(string(res)) log.Debugln(string(res))
return nil return nil
} }
params := jsoniter.Get(res, "resumable").Get("params")
endpoint := params.Get("endpoint").ToString() params := resp.Resumable.Params
endpointS := strings.Split(endpoint, ".") endpoint := strings.Join(strings.Split(params.Endpoint, ".")[1:], ".")
endpoint = strings.Join(endpointS[1:], ".")
accessKeyId := params.Get("access_key_id").ToString()
accessKeySecret := params.Get("access_key_secret").ToString()
securityToken := params.Get("security_token").ToString()
key := params.Get("key").ToString()
bucket := params.Get("bucket").ToString()
cfg := &aws.Config{ cfg := &aws.Config{
Credentials: credentials.NewStaticCredentials(accessKeyId, accessKeySecret, securityToken), Credentials: credentials.NewStaticCredentials(params.AccessKeyID, params.AccessKeySecret, params.SecurityToken),
Region: aws.String("pikpak"), Region: aws.String("pikpak"),
Endpoint: &endpoint, Endpoint: &endpoint,
} }
@ -185,8 +177,8 @@ func (d *PikPak) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
} }
uploader := s3manager.NewUploader(ss) uploader := s3manager.NewUploader(ss)
input := &s3manager.UploadInput{ input := &s3manager.UploadInput{
Bucket: &bucket, Bucket: &params.Bucket,
Key: &key, Key: &params.Key,
Body: tempFile, Body: tempFile,
} }
_, err = uploader.UploadWithContext(ctx, input) _, err = uploader.UploadWithContext(ctx, input)

View File

@ -73,3 +73,23 @@ type Media struct {
IsVisible bool `json:"is_visible"` IsVisible bool `json:"is_visible"`
Category string `json:"category"` Category string `json:"category"`
} }
type UploadTaskData struct {
UploadType string `json:"upload_type"`
//UPLOAD_TYPE_RESUMABLE
Resumable *struct {
Kind string `json:"kind"`
Params struct {
AccessKeyID string `json:"access_key_id"`
AccessKeySecret string `json:"access_key_secret"`
Bucket string `json:"bucket"`
Endpoint string `json:"endpoint"`
Expiration time.Time `json:"expiration"`
Key string `json:"key"`
SecurityToken string `json:"security_token"`
} `json:"params"`
Provider string `json:"provider"`
} `json:"resumable"`
File File `json:"file"`
}

View File

@ -1,7 +1,10 @@
package pikpak package pikpak
import ( import (
"crypto/sha1"
"encoding/hex"
"errors" "errors"
"io"
"net/http" "net/http"
"github.com/alist-org/alist/v3/drivers/base" "github.com/alist-org/alist/v3/drivers/base"
@ -123,3 +126,28 @@ func (d *PikPak) getFiles(id string) ([]File, error) {
} }
return res, nil return res, nil
} }
func getGcid(r io.Reader, size int64) (string, error) {
calcBlockSize := func(j int64) int64 {
var psize int64 = 0x40000
for float64(j)/float64(psize) > 0x200 && psize < 0x200000 {
psize = psize << 1
}
return psize
}
hash1 := sha1.New()
hash2 := sha1.New()
readSize := calcBlockSize(size)
for {
hash2.Reset()
if n, err := io.CopyN(hash2, r, readSize); err != nil && n == 0 {
if err != io.EOF {
return "", err
}
break
}
hash1.Write(hash2.Sum(nil))
}
return hex.EncodeToString(hash1.Sum(nil)), nil
}