diff --git a/drivers/pikpak/driver.go b/drivers/pikpak/driver.go index f3676b8291b..e27263ddbb7 100644 --- a/drivers/pikpak/driver.go +++ b/drivers/pikpak/driver.go @@ -17,13 +17,14 @@ import ( "github.com/aws/aws-sdk-go/service/s3/s3manager" "github.com/go-resty/resty/v2" log "github.com/sirupsen/logrus" + "golang.org/x/oauth2" ) type PikPak struct { model.Storage Addition - RefreshToken string - AccessToken string + + oauth2Token oauth2.TokenSource } func (d *PikPak) Config() driver.Config { @@ -34,8 +35,32 @@ func (d *PikPak) GetAddition() driver.Additional { return &d.Addition } -func (d *PikPak) Init(ctx context.Context) error { - return d.login() +func (d *PikPak) Init(ctx context.Context) (err error) { + if d.ClientID == "" || d.ClientSecret == "" { + d.ClientID = "YNxT9w7GMdWvEOKa" + d.ClientSecret = "dbw2OtmVEeuUvIptb1Coyg" + } + + withClient := func(ctx context.Context) context.Context { + return context.WithValue(ctx, oauth2.HTTPClient, base.HttpClient) + } + + oauth2Config := &oauth2.Config{ + ClientID: d.ClientID, + ClientSecret: d.ClientSecret, + Endpoint: oauth2.Endpoint{ + AuthURL: "https://user.mypikpak.com/v1/auth/signin", + TokenURL: "https://user.mypikpak.com/v1/auth/token", + AuthStyle: oauth2.AuthStyleInParams, + }, + } + + oauth2Token, err := oauth2Config.PasswordCredentialsToken(withClient(ctx), d.Username, d.Password) + if err != nil { + return err + } + d.oauth2Token = oauth2Config.TokenSource(withClient(context.Background()), oauth2Token) + return nil } func (d *PikPak) Drop(ctx context.Context) error { diff --git a/drivers/pikpak/meta.go b/drivers/pikpak/meta.go index 3512c44b93b..c462ed13d6b 100644 --- a/drivers/pikpak/meta.go +++ b/drivers/pikpak/meta.go @@ -9,6 +9,8 @@ type Addition struct { driver.RootID Username string `json:"username" required:"true"` Password string `json:"password" required:"true"` + ClientID string `json:"client_id" required:"true" default:"YNxT9w7GMdWvEOKa"` + ClientSecret string `json:"client_secret" required:"true" default:"dbw2OtmVEeuUvIptb1Coyg"` DisableMediaLink bool `json:"disable_media_link"` } diff --git a/drivers/pikpak/util.go b/drivers/pikpak/util.go index 71ad1dca8a3..0edfc384eba 100644 --- a/drivers/pikpak/util.go +++ b/drivers/pikpak/util.go @@ -1,78 +1,24 @@ package pikpak import ( - "crypto/sha1" - "encoding/hex" "errors" - "github.com/alist-org/alist/v3/pkg/utils" - "io" "net/http" "github.com/alist-org/alist/v3/drivers/base" - "github.com/alist-org/alist/v3/internal/op" "github.com/go-resty/resty/v2" - jsoniter "github.com/json-iterator/go" ) // do others that not defined in Driver interface -func (d *PikPak) login() error { - url := "https://user.mypikpak.com/v1/auth/signin" - var e RespErr - res, err := base.RestyClient.R().SetError(&e).SetBody(base.Json{ - "captcha_token": "", - "client_id": "YNxT9w7GMdWvEOKa", - "client_secret": "dbw2OtmVEeuUvIptb1Coyg", - "username": d.Username, - "password": d.Password, - }).Post(url) - if err != nil { - return err - } - if e.ErrorCode != 0 { - return errors.New(e.Error) - } - data := res.Body() - d.RefreshToken = jsoniter.Get(data, "refresh_token").ToString() - d.AccessToken = jsoniter.Get(data, "access_token").ToString() - return nil -} +func (d *PikPak) request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) { + req := base.RestyClient.R() -func (d *PikPak) refreshToken() error { - url := "https://user.mypikpak.com/v1/auth/token" - var e RespErr - res, err := base.RestyClient.R().SetError(&e). - SetHeader("user-agent", "").SetBody(base.Json{ - "client_id": "YNxT9w7GMdWvEOKa", - "client_secret": "dbw2OtmVEeuUvIptb1Coyg", - "grant_type": "refresh_token", - "refresh_token": d.RefreshToken, - }).Post(url) + token, err := d.oauth2Token.Token() if err != nil { - d.Status = err.Error() - op.MustSaveDriverStorage(d) - return err - } - if e.ErrorCode != 0 { - if e.ErrorCode == 4126 { - // refresh_token invalid, re-login - return d.login() - } - d.Status = e.Error - op.MustSaveDriverStorage(d) - return errors.New(e.Error) + return nil, err } - data := res.Body() - d.Status = "work" - d.RefreshToken = jsoniter.Get(data, "refresh_token").ToString() - d.AccessToken = jsoniter.Get(data, "access_token").ToString() - op.MustSaveDriverStorage(d) - return nil -} + req.SetAuthScheme(token.TokenType).SetAuthToken(token.AccessToken) -func (d *PikPak) request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) { - req := base.RestyClient.R() - req.SetHeader("Authorization", "Bearer "+d.AccessToken) if callback != nil { callback(req) } @@ -85,17 +31,9 @@ func (d *PikPak) request(url string, method string, callback base.ReqCallback, r if err != nil { return nil, err } + if e.ErrorCode != 0 { - if e.ErrorCode == 16 { - // login / refresh token - err = d.refreshToken() - if err != nil { - return nil, err - } - return d.request(url, method, callback, resp) - } else { - return nil, errors.New(e.Error) - } + return nil, errors.New(e.Error) } return res.Body(), nil } @@ -127,28 +65,3 @@ func (d *PikPak) getFiles(id string) ([]File, error) { } 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 := utils.CopyWithBufferN(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 -} diff --git a/drivers/pikpak_share/driver.go b/drivers/pikpak_share/driver.go index 3003ff48860..58c2c8c4b55 100644 --- a/drivers/pikpak_share/driver.go +++ b/drivers/pikpak_share/driver.go @@ -4,17 +4,18 @@ import ( "context" "net/http" + "github.com/alist-org/alist/v3/drivers/base" "github.com/alist-org/alist/v3/internal/driver" "github.com/alist-org/alist/v3/internal/model" "github.com/alist-org/alist/v3/pkg/utils" "github.com/go-resty/resty/v2" + "golang.org/x/oauth2" ) type PikPakShare struct { model.Storage Addition - RefreshToken string - AccessToken string + oauth2Token oauth2.TokenSource PassCodeToken string } @@ -27,10 +28,31 @@ func (d *PikPakShare) GetAddition() driver.Additional { } func (d *PikPakShare) Init(ctx context.Context) error { - err := d.login() + if d.ClientID == "" || d.ClientSecret == "" { + d.ClientID = "YNxT9w7GMdWvEOKa" + d.ClientSecret = "dbw2OtmVEeuUvIptb1Coyg" + } + + withClient := func(ctx context.Context) context.Context { + return context.WithValue(ctx, oauth2.HTTPClient, base.HttpClient) + } + + oauth2Config := &oauth2.Config{ + ClientID: d.ClientID, + ClientSecret: d.ClientSecret, + Endpoint: oauth2.Endpoint{ + AuthURL: "https://user.mypikpak.com/v1/auth/signin", + TokenURL: "https://user.mypikpak.com/v1/auth/token", + AuthStyle: oauth2.AuthStyleInParams, + }, + } + + oauth2Token, err := oauth2Config.PasswordCredentialsToken(withClient(ctx), d.Username, d.Password) if err != nil { return err } + d.oauth2Token = oauth2Config.TokenSource(withClient(context.Background()), oauth2Token) + if d.SharePwd != "" { err = d.getSharePassToken() if err != nil { @@ -67,8 +89,14 @@ func (d *PikPakShare) Link(ctx context.Context, file model.Obj, args model.LinkA if err != nil { return nil, err } + + downloadUrl := resp.FileInfo.WebContentLink + if downloadUrl == "" && len(resp.FileInfo.Medias) > 0 { + downloadUrl = resp.FileInfo.Medias[0].Link.Url + } + link := model.Link{ - URL: resp.FileInfo.WebContentLink, + URL: downloadUrl, } return &link, nil } diff --git a/drivers/pikpak_share/meta.go b/drivers/pikpak_share/meta.go index bf77e22b3cf..5d05badb590 100644 --- a/drivers/pikpak_share/meta.go +++ b/drivers/pikpak_share/meta.go @@ -7,10 +7,12 @@ import ( type Addition struct { driver.RootID - Username string `json:"username" required:"true"` - Password string `json:"password" required:"true"` - ShareId string `json:"share_id" required:"true"` - SharePwd string `json:"share_pwd"` + Username string `json:"username" required:"true"` + Password string `json:"password" required:"true"` + ShareId string `json:"share_id" required:"true"` + SharePwd string `json:"share_pwd"` + ClientID string `json:"client_id" required:"true" default:"YNxT9w7GMdWvEOKa"` + ClientSecret string `json:"client_secret" required:"true" default:"dbw2OtmVEeuUvIptb1Coyg"` } var config = driver.Config{ diff --git a/drivers/pikpak_share/util.go b/drivers/pikpak_share/util.go index e62f17842c6..41bb30d4aa6 100644 --- a/drivers/pikpak_share/util.go +++ b/drivers/pikpak_share/util.go @@ -5,70 +5,18 @@ import ( "net/http" "github.com/alist-org/alist/v3/drivers/base" - "github.com/alist-org/alist/v3/internal/op" "github.com/go-resty/resty/v2" - jsoniter "github.com/json-iterator/go" ) -// do others that not defined in Driver interface - -func (d *PikPakShare) login() error { - url := "https://user.mypikpak.com/v1/auth/signin" - var e RespErr - res, err := base.RestyClient.R().SetError(&e).SetBody(base.Json{ - "captcha_token": "", - "client_id": "YNxT9w7GMdWvEOKa", - "client_secret": "dbw2OtmVEeuUvIptb1Coyg", - "username": d.Username, - "password": d.Password, - }).Post(url) - if err != nil { - return err - } - if e.ErrorCode != 0 { - return errors.New(e.Error) - } - data := res.Body() - d.RefreshToken = jsoniter.Get(data, "refresh_token").ToString() - d.AccessToken = jsoniter.Get(data, "access_token").ToString() - return nil -} +func (d *PikPakShare) request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) { + req := base.RestyClient.R() -func (d *PikPakShare) refreshToken() error { - url := "https://user.mypikpak.com/v1/auth/token" - var e RespErr - res, err := base.RestyClient.R().SetError(&e). - SetHeader("user-agent", "").SetBody(base.Json{ - "client_id": "YNxT9w7GMdWvEOKa", - "client_secret": "dbw2OtmVEeuUvIptb1Coyg", - "grant_type": "refresh_token", - "refresh_token": d.RefreshToken, - }).Post(url) + token, err := d.oauth2Token.Token() if err != nil { - d.Status = err.Error() - op.MustSaveDriverStorage(d) - return err - } - if e.ErrorCode != 0 { - if e.ErrorCode == 4126 { - // refresh_token invalid, re-login - return d.login() - } - d.Status = e.Error - op.MustSaveDriverStorage(d) - return errors.New(e.Error) + return nil, err } - data := res.Body() - d.Status = "work" - d.RefreshToken = jsoniter.Get(data, "refresh_token").ToString() - d.AccessToken = jsoniter.Get(data, "access_token").ToString() - op.MustSaveDriverStorage(d) - return nil -} + req.SetAuthScheme(token.TokenType).SetAuthToken(token.AccessToken) -func (d *PikPakShare) request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) { - req := base.RestyClient.R() - req.SetHeader("Authorization", "Bearer "+d.AccessToken) if callback != nil { callback(req) } @@ -82,14 +30,6 @@ func (d *PikPakShare) request(url string, method string, callback base.ReqCallba return nil, err } if e.ErrorCode != 0 { - if e.ErrorCode == 16 { - // login / refresh token - err = d.refreshToken() - if err != nil { - return nil, err - } - return d.request(url, method, callback, resp) - } return nil, errors.New(e.Error) } return res.Body(), nil