From 8822eef97e9d127f291a3fc03927a459a03bf3f1 Mon Sep 17 00:00:00 2001 From: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com> Date: Tue, 17 Jun 2025 22:13:28 +0800 Subject: [PATCH] chore(api):Add online api refresh method (#143) * Add Official API Refresh Interface(Baiduyun) * add UseOnlineAPI & APIAddress add _refreshToken using APIAddress * fix return * Modify the frontend display using the default API refresh method * Fixed display and operation related issues * fixed aliyundrive_open old refresh --------- Co-authored-by: Suyunmeng --- drivers/115_open/meta.go | 6 ++-- drivers/115_open/util.go | 46 +++++++++++++++++++++++++++++++ drivers/aliyundrive_open/meta.go | 7 +++-- drivers/aliyundrive_open/util.go | 34 +++++++++++++++++++++-- drivers/baidu_netdisk/meta.go | 6 ++-- drivers/baidu_netdisk/util.go | 47 ++++++++++++++++++++++++++++---- drivers/google_drive/meta.go | 6 ++-- drivers/google_drive/util.go | 33 ++++++++++++++++++++++ drivers/onedrive/meta.go | 6 ++-- drivers/onedrive/util.go | 31 +++++++++++++++++++++ drivers/yandex_disk/meta.go | 6 ++-- drivers/yandex_disk/util.go | 31 +++++++++++++++++++++ 12 files changed, 237 insertions(+), 22 deletions(-) diff --git a/drivers/115_open/meta.go b/drivers/115_open/meta.go index 3cf6760e3..ba7510598 100644 --- a/drivers/115_open/meta.go +++ b/drivers/115_open/meta.go @@ -9,11 +9,13 @@ type Addition struct { // Usually one of two driver.RootID // define other - RefreshToken string `json:"refresh_token" required:"true"` OrderBy string `json:"order_by" type:"select" options:"file_name,file_size,user_utime,file_type"` OrderDirection string `json:"order_direction" type:"select" options:"asc,desc"` LimitRate float64 `json:"limit_rate" type:"float" default:"1" help:"limit all api request rate ([limit]r/1s)"` - AccessToken string + UseOnlineAPI bool `json:"use_online_api" default:"true"` + APIAddress string `json:"api_url_address" default:"https://api.oplist.org/115cloud/renewapi"` + RefreshToken string `json:"refresh_token" required:"true"` + AccessToken string `json:"access_token" required:"true"` } var config = driver.Config{ diff --git a/drivers/115_open/util.go b/drivers/115_open/util.go index ee0216597..f5ad1c84b 100644 --- a/drivers/115_open/util.go +++ b/drivers/115_open/util.go @@ -1,3 +1,49 @@ package _115_open +import ( + "errors" + "fmt" + "github.com/OpenListTeam/OpenList/drivers/base" + "github.com/OpenListTeam/OpenList/internal/errs" + "github.com/OpenListTeam/OpenList/internal/op" +) + +func (d *Open115) refreshToken() error { + err := d._refreshToken() + if err != nil && errors.Is(err, errs.EmptyToken) { + err = d._refreshToken() + } + return err +} + +func (d *Open115) _refreshToken() error { + // 使用在线API刷新Token,无需ClientID和ClientSecret + if d.Addition.UseOnlineAPI && len(d.Addition.APIAddress) > 0 { + u := d.APIAddress + var resp struct { + RefreshToken string `json:"refresh_token"` + AccessToken string `json:"access_token"` + } + _, err := base.RestyClient.R(). + SetResult(&resp). + SetQueryParams(map[string]string{ + "refresh_ui": d.Addition.RefreshToken, + "server_use": "true", + "driver_txt": "115cloud_go", + }). + Get(u) + if err != nil { + return err + } + if resp.RefreshToken == "" || resp.AccessToken == "" { + return fmt.Errorf("empty token returned from official API") + } + d.AccessToken = resp.AccessToken + d.RefreshToken = resp.RefreshToken + op.MustSaveDriverStorage(d) + return nil + } + return nil +} + // do others that not defined in Driver interface diff --git a/drivers/aliyundrive_open/meta.go b/drivers/aliyundrive_open/meta.go index 307963d51..1839b8870 100644 --- a/drivers/aliyundrive_open/meta.go +++ b/drivers/aliyundrive_open/meta.go @@ -11,9 +11,10 @@ type Addition struct { RefreshToken string `json:"refresh_token" required:"true"` OrderBy string `json:"order_by" type:"select" options:"name,size,updated_at,created_at"` OrderDirection string `json:"order_direction" type:"select" options:"ASC,DESC"` - OauthTokenURL string `json:"oauth_token_url" default:"https://example.com/alist/ali_open/token"` // TODO: Replace this with a community hosted api endpoint - ClientID string `json:"client_id" required:"false" help:"Keep it empty if you don't have one"` - ClientSecret string `json:"client_secret" required:"false" help:"Keep it empty if you don't have one"` + UseOnlineAPI bool `json:"use_online_api" default:"true"` + APIAddress string `json:"api_url_address" default:"https://api.oplist.org/alicloud/renewapi"` + ClientID string `json:"client_id" help:"Keep it empty if you don't have one"` + ClientSecret string `json:"client_secret" help:"Keep it empty if you don't have one"` RemoveWay string `json:"remove_way" required:"true" type:"select" options:"trash,delete"` RapidUpload bool `json:"rapid_upload" help:"If you enable this option, the file will be uploaded to the server first, so the progress will be incorrect"` InternalUpload bool `json:"internal_upload" help:"If you are using Aliyun ECS is located in Beijing, you can turn it on to boost the upload speed"` diff --git a/drivers/aliyundrive_open/util.go b/drivers/aliyundrive_open/util.go index 6a2169e01..6a98b3649 100644 --- a/drivers/aliyundrive_open/util.go +++ b/drivers/aliyundrive_open/util.go @@ -20,10 +20,38 @@ import ( // do others that not defined in Driver interface func (d *AliyundriveOpen) _refreshToken() (string, string, error) { - url := API_URL + "/oauth/access_token" - if d.OauthTokenURL != "" && d.ClientID == "" { - url = d.OauthTokenURL + // 使用在线API刷新Token,无需ClientID和ClientSecret + if d.UseOnlineAPI && len(d.APIAddress) > 0 { + u := d.APIAddress + var resp struct { + RefreshToken string `json:"refresh_token"` + AccessToken string `json:"access_token"` + } + _, err := base.RestyClient.R(). + SetResult(&resp). + SetQueryParams(map[string]string{ + "refresh_ui": d.RefreshToken, + "server_use": "true", + "driver_txt": "alicloud_qr", + }). + Get(u) + if err != nil { + return "", "", err + } + if resp.RefreshToken == "" || resp.AccessToken == "" { + return "", "", fmt.Errorf("empty token returned from official API") + } + d.AccessToken = resp.AccessToken + d.RefreshToken = resp.RefreshToken + op.MustSaveDriverStorage(d) + return "", "", nil } + // 使用本地客户端的情况下检查是否为空 + if d.ClientID == "" || d.ClientSecret == "" { + return "", "", fmt.Errorf("empty ClientID or ClientSecret") + } + // 走原有的刷新逻辑 + url := API_URL + "/oauth/access_token" //var resp base.TokenResp var e ErrResp res, err := base.RestyClient.R(). diff --git a/drivers/baidu_netdisk/meta.go b/drivers/baidu_netdisk/meta.go index 803440148..48a704791 100644 --- a/drivers/baidu_netdisk/meta.go +++ b/drivers/baidu_netdisk/meta.go @@ -11,8 +11,10 @@ type Addition struct { 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"` DownloadAPI string `json:"download_api" type:"select" options:"official,crack,crack_video" default:"official"` - ClientID string `json:"client_id" required:"true" default:"iYCeC9g08h5vuP9UqvPHKKSVrKFXGa1v"` - ClientSecret string `json:"client_secret" required:"true" default:"jXiFMOPVPCWlO2M5CwWQzffpNPaGTRBG"` + UseOnlineAPI bool `json:"use_online_api" default:"true"` + APIAddress string `json:"api_url_address" default:"https://api.oplist.org/baiduyun/renewapi"` + ClientID string `json:"client_id"` + ClientSecret string `json:"client_secret"` CustomCrackUA string `json:"custom_crack_ua" required:"true" default:"netdisk"` AccessToken string UploadThread string `json:"upload_thread" default:"3" help:"1<=thread<=32"` diff --git a/drivers/baidu_netdisk/util.go b/drivers/baidu_netdisk/util.go index 3fd395cde..9b275ddea 100644 --- a/drivers/baidu_netdisk/util.go +++ b/drivers/baidu_netdisk/util.go @@ -31,15 +31,50 @@ func (d *BaiduNetdisk) refreshToken() error { } func (d *BaiduNetdisk) _refreshToken() error { + // 使用在线API刷新Token,无需ClientID和ClientSecret + if d.UseOnlineAPI && len(d.APIAddress) > 0 { + u := d.APIAddress + var resp struct { + RefreshToken string `json:"refresh_token"` + AccessToken string `json:"access_token"` + } + _, err := base.RestyClient.R(). + SetResult(&resp). + SetQueryParams(map[string]string{ + "refresh_ui": d.RefreshToken, + "server_use": "true", + "driver_txt": "baiduyun_go", + }). + Get(u) + if err != nil { + return err + } + if resp.RefreshToken == "" || resp.AccessToken == "" { + return fmt.Errorf("empty token returned from official API") + } + d.AccessToken = resp.AccessToken + d.RefreshToken = resp.RefreshToken + op.MustSaveDriverStorage(d) + return nil + } + // 使用本地客户端的情况下检查是否为空 + if d.ClientID == "" || d.ClientSecret == "" { + return fmt.Errorf("empty ClientID or ClientSecret") + } + // 走原有的刷新逻辑 u := "https://openapi.baidu.com/oauth/2.0/token" var resp base.TokenResp var e TokenErrResp - _, err := base.RestyClient.R().SetResult(&resp).SetError(&e).SetQueryParams(map[string]string{ - "grant_type": "refresh_token", - "refresh_token": d.RefreshToken, - "client_id": d.ClientID, - "client_secret": d.ClientSecret, - }).Get(u) + _, err := base.RestyClient.R(). + SetResult(&resp). + SetError(&e). + SetQueryParams(map[string]string{ + "grant_type": "refresh_token", + "refresh_token": d.RefreshToken, + "client_id": d.ClientID, + "client_secret": d.ClientSecret, + }). + Get(u) if err != nil { return err } diff --git a/drivers/google_drive/meta.go b/drivers/google_drive/meta.go index da55ae8a2..419c632bc 100644 --- a/drivers/google_drive/meta.go +++ b/drivers/google_drive/meta.go @@ -10,8 +10,10 @@ type Addition struct { RefreshToken string `json:"refresh_token" required:"true"` OrderBy string `json:"order_by" type:"string" help:"such as: folder,name,modifiedTime"` OrderDirection string `json:"order_direction" type:"select" options:"asc,desc"` - ClientID string `json:"client_id" required:"true" default:"202264815644.apps.googleusercontent.com"` - ClientSecret string `json:"client_secret" required:"true" default:"X4Z3ca8xfWDb1Voo-F9a7ZxJ"` + UseOnlineAPI bool `json:"use_online_api" default:"true"` + APIAddress string `json:"api_url_address" default:"https://api.oplist.org/googleui/renewapi"` + ClientID string `json:"client_id"` + ClientSecret string `json:"client_secret"` ChunkSize int64 `json:"chunk_size" type:"number" default:"5" help:"chunk size while uploading (unit: MB)"` } diff --git a/drivers/google_drive/util.go b/drivers/google_drive/util.go index 2ea0289b5..55c7755d7 100644 --- a/drivers/google_drive/util.go +++ b/drivers/google_drive/util.go @@ -5,6 +5,7 @@ import ( "crypto/x509" "encoding/pem" "fmt" + "github.com/OpenListTeam/OpenList/internal/op" "net/http" "os" "regexp" @@ -37,6 +38,38 @@ type googleDriveServiceAccount struct { } func (d *GoogleDrive) refreshToken() error { + // 使用在线API刷新Token,无需ClientID和ClientSecret + if d.UseOnlineAPI && len(d.APIAddress) > 0 { + u := d.APIAddress + var resp struct { + RefreshToken string `json:"refresh_token"` + AccessToken string `json:"access_token"` + } + _, err := base.RestyClient.R(). + SetResult(&resp). + SetQueryParams(map[string]string{ + "refresh_ui": d.RefreshToken, + "server_use": "true", + "driver_txt": "googleui_go", + }). + Get(u) + if err != nil { + return err + } + if resp.RefreshToken == "" || resp.AccessToken == "" { + return fmt.Errorf("empty token returned from official API") + } + d.AccessToken = resp.AccessToken + d.RefreshToken = resp.RefreshToken + op.MustSaveDriverStorage(d) + return nil + } + // 使用本地客户端的情况下检查是否为空 + if d.ClientID == "" || d.ClientSecret == "" { + return fmt.Errorf("empty ClientID or ClientSecret") + } + // 走原有的刷新逻辑 + // googleDriveServiceAccountFile gdsaFile gdsaFile, gdsaFileErr := os.Stat(d.RefreshToken) if gdsaFileErr == nil { diff --git a/drivers/onedrive/meta.go b/drivers/onedrive/meta.go index 82f0a4d29..de49c87fe 100644 --- a/drivers/onedrive/meta.go +++ b/drivers/onedrive/meta.go @@ -9,8 +9,10 @@ type Addition struct { driver.RootPath Region string `json:"region" type:"select" required:"true" options:"global,cn,us,de" default:"global"` IsSharepoint bool `json:"is_sharepoint"` - ClientID string `json:"client_id" required:"true"` - ClientSecret string `json:"client_secret" required:"true"` + UseOnlineAPI bool `json:"use_online_api" default:"true"` + APIAddress string `json:"api_url_address" default:"https://api.oplist.org/onedrive/renewapi"` + ClientID string `json:"client_id"` + ClientSecret string `json:"client_secret"` RedirectUri string `json:"redirect_uri" required:"true" default:"https://api.oplist.org/onedrive/callback"` RefreshToken string `json:"refresh_token" required:"true"` SiteId string `json:"site_id"` diff --git a/drivers/onedrive/util.go b/drivers/onedrive/util.go index 8cac552c8..01085b90a 100644 --- a/drivers/onedrive/util.go +++ b/drivers/onedrive/util.go @@ -72,6 +72,37 @@ func (d *Onedrive) refreshToken() error { } func (d *Onedrive) _refreshToken() error { + // 使用在线API刷新Token,无需ClientID和ClientSecret + if d.UseOnlineAPI && len(d.APIAddress) > 0 { + u := d.APIAddress + var resp struct { + RefreshToken string `json:"refresh_token"` + AccessToken string `json:"access_token"` + } + _, err := base.RestyClient.R(). + SetResult(&resp). + SetQueryParams(map[string]string{ + "refresh_ui": d.RefreshToken, + "server_use": "true", + "driver_txt": "onedrive_pr", + }). + Get(u) + if err != nil { + return err + } + if resp.RefreshToken == "" || resp.AccessToken == "" { + return fmt.Errorf("empty token returned from official API") + } + d.AccessToken = resp.AccessToken + d.RefreshToken = resp.RefreshToken + op.MustSaveDriverStorage(d) + return nil + } + // 使用本地客户端的情况下检查是否为空 + if d.ClientID == "" || d.ClientSecret == "" { + return fmt.Errorf("empty ClientID or ClientSecret") + } + // 走原有的刷新逻辑 url := d.GetMetaUrl(true, "") + "/common/oauth2/v2.0/token" var resp base.TokenResp var e TokenErr diff --git a/drivers/yandex_disk/meta.go b/drivers/yandex_disk/meta.go index 91ef9000f..a01264a36 100644 --- a/drivers/yandex_disk/meta.go +++ b/drivers/yandex_disk/meta.go @@ -10,8 +10,10 @@ type Addition struct { OrderBy string `json:"order_by" type:"select" options:"name,path,created,modified,size" default:"name"` OrderDirection string `json:"order_direction" type:"select" options:"asc,desc" default:"asc"` driver.RootPath - ClientID string `json:"client_id" required:"true" default:"a78d5a69054042fa936f6c77f9a0ae8b"` - ClientSecret string `json:"client_secret" required:"true" default:"9c119bbb04b346d2a52aa64401936b2b"` + UseOnlineAPI bool `json:"use_online_api" default:"true"` + APIAddress string `json:"api_url_address" default:"https://api.oplist.org/yandexui/renewapi"` + ClientID string `json:"client_id"` + ClientSecret string `json:"client_secret"` } var config = driver.Config{ diff --git a/drivers/yandex_disk/util.go b/drivers/yandex_disk/util.go index 350d6a954..8419b9c8b 100644 --- a/drivers/yandex_disk/util.go +++ b/drivers/yandex_disk/util.go @@ -14,6 +14,37 @@ import ( // do others that not defined in Driver interface func (d *YandexDisk) refreshToken() error { + // 使用在线API刷新Token,无需ClientID和ClientSecret + if d.UseOnlineAPI && len(d.APIAddress) > 0 { + u := d.APIAddress + var resp struct { + RefreshToken string `json:"refresh_token"` + AccessToken string `json:"access_token"` + } + _, err := base.RestyClient.R(). + SetResult(&resp). + SetQueryParams(map[string]string{ + "refresh_ui": d.RefreshToken, + "server_use": "true", + "driver_txt": "yandexui_go", + }). + Get(u) + if err != nil { + return err + } + if resp.RefreshToken == "" || resp.AccessToken == "" { + return fmt.Errorf("empty token returned from official API") + } + d.AccessToken = resp.AccessToken + d.RefreshToken = resp.RefreshToken + op.MustSaveDriverStorage(d) + return nil + } + // 使用本地客户端的情况下检查是否为空 + if d.ClientID == "" || d.ClientSecret == "" { + return fmt.Errorf("empty ClientID or ClientSecret") + } + // 走原有的刷新逻辑 u := "https://oauth.yandex.com/token" var resp base.TokenResp var e TokenErrResp