mirror of https://github.com/Xhofe/alist
feat: Support 123pan safebox (#9311)
* feat(meta): Added a SafePassword field - Added the SafePassword field to meta.go - Revised the field format to align with the code style - The SafePassword field is used to supplement the extended functionality * feat(driver): Added support for safe unlocking logic - Added safe file unlocking logic in `driver.go`, returning an error if unlocking fails. - Introduced the `safeBoxUnlocked` variable of type `sync.Map` to record the IDs of unlocked files. - Enhanced error handling logic to automatically attempt to unlock safe files and re-retrieve the file list. - Added the `IsLock` field to file types in `types.go` to identify whether they are safe files. - Added a constant definition for the `SafeBoxUnlock` interface address in `util.go`. - Added the `unlockSafeBox` method to unlock a safe with a specified file ID via the API. - Optimized the file retrieval logic to automatically call the unlock method when the safe is locked. * Refactor (driver): Optimize lock field type - Changed the `IsLock` field type from `int` to `bool` for better semantics. - Updated the check logic to use direct Boolean comparisons to improve code readability and accuracy.main beta
parent
930f9f6096
commit
fcbc79cb24
|
@ -6,6 +6,8 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
|
@ -28,7 +30,8 @@ import (
|
|||
type Pan123 struct {
|
||||
model.Storage
|
||||
Addition
|
||||
apiRateLimit sync.Map
|
||||
apiRateLimit sync.Map
|
||||
safeBoxUnlocked sync.Map
|
||||
}
|
||||
|
||||
func (d *Pan123) Config() driver.Config {
|
||||
|
@ -52,9 +55,26 @@ func (d *Pan123) Drop(ctx context.Context) error {
|
|||
}
|
||||
|
||||
func (d *Pan123) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
||||
if f, ok := dir.(File); ok && f.IsLock {
|
||||
if err := d.unlockSafeBox(f.FileId); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
files, err := d.getFiles(ctx, dir.GetID(), dir.GetName())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
msg := strings.ToLower(err.Error())
|
||||
if strings.Contains(msg, "safe box") || strings.Contains(err.Error(), "保险箱") {
|
||||
if id, e := strconv.ParseInt(dir.GetID(), 10, 64); e == nil {
|
||||
if e = d.unlockSafeBox(id); e == nil {
|
||||
files, err = d.getFiles(ctx, dir.GetID(), dir.GetName())
|
||||
} else {
|
||||
return nil, e
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return utils.SliceConvert(files, func(src File) (model.Obj, error) {
|
||||
return src, nil
|
||||
|
|
|
@ -6,8 +6,9 @@ import (
|
|||
)
|
||||
|
||||
type Addition struct {
|
||||
Username string `json:"username" required:"true"`
|
||||
Password string `json:"password" required:"true"`
|
||||
Username string `json:"username" required:"true"`
|
||||
Password string `json:"password" required:"true"`
|
||||
SafePassword string `json:"safe_password"`
|
||||
driver.RootID
|
||||
//OrderBy string `json:"order_by" type:"select" options:"file_id,file_name,size,update_at" default:"file_name"`
|
||||
//OrderDirection string `json:"order_direction" type:"select" options:"asc,desc" default:"asc"`
|
||||
|
|
|
@ -20,6 +20,7 @@ type File struct {
|
|||
Etag string `json:"Etag"`
|
||||
S3KeyFlag string `json:"S3KeyFlag"`
|
||||
DownloadUrl string `json:"DownloadUrl"`
|
||||
IsLock bool `json:"IsLock"`
|
||||
}
|
||||
|
||||
func (f File) CreateTime() time.Time {
|
||||
|
|
|
@ -43,6 +43,7 @@ const (
|
|||
S3Auth = MainApi + "/file/s3_upload_object/auth"
|
||||
UploadCompleteV2 = MainApi + "/file/upload_complete/v2"
|
||||
S3Complete = MainApi + "/file/s3_complete_multipart_upload"
|
||||
SafeBoxUnlock = MainApi + "/restful/goapi/v1/file/safe_box/auth/unlockbox"
|
||||
//AuthKeySalt = "8-8D$sL8gPjom7bk#cY"
|
||||
)
|
||||
|
||||
|
@ -238,6 +239,22 @@ do:
|
|||
return body, nil
|
||||
}
|
||||
|
||||
func (d *Pan123) unlockSafeBox(fileId int64) error {
|
||||
if _, ok := d.safeBoxUnlocked.Load(fileId); ok {
|
||||
return nil
|
||||
}
|
||||
data := base.Json{"password": d.SafePassword}
|
||||
url := fmt.Sprintf("%s?fileId=%d", SafeBoxUnlock, fileId)
|
||||
_, err := d.Request(url, http.MethodPost, func(req *resty.Request) {
|
||||
req.SetBody(data)
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.safeBoxUnlocked.Store(fileId, true)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Pan123) getFiles(ctx context.Context, parentId string, name string) ([]File, error) {
|
||||
page := 1
|
||||
total := 0
|
||||
|
@ -267,6 +284,15 @@ func (d *Pan123) getFiles(ctx context.Context, parentId string, name string) ([]
|
|||
req.SetQueryParams(query)
|
||||
}, &resp)
|
||||
if err != nil {
|
||||
msg := strings.ToLower(err.Error())
|
||||
if strings.Contains(msg, "safe box") || strings.Contains(err.Error(), "保险箱") {
|
||||
if fid, e := strconv.ParseInt(parentId, 10, 64); e == nil {
|
||||
if e = d.unlockSafeBox(fid); e == nil {
|
||||
return d.getFiles(ctx, parentId, name)
|
||||
}
|
||||
return nil, e
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
log.Debug(string(_res))
|
||||
|
|
Loading…
Reference in New Issue