change login routine

This commit is contained in:
tickstep
2024-03-02 00:55:46 +08:00
parent c350cadba4
commit e5f63c60e9
33 changed files with 551 additions and 504 deletions
+17 -17
View File
@@ -303,7 +303,7 @@ func CmdAlbum() cli.Command {
func RunAlbumList() { func RunAlbumList() {
activeUser := GetActiveUser() activeUser := GetActiveUser()
records, err := activeUser.PanClient().AlbumListGetAll(&aliyunpan.AlbumListParam{}) records, err := activeUser.PanClient().WebapiPanClient().AlbumListGetAll(&aliyunpan.AlbumListParam{})
if err != nil { if err != nil {
fmt.Printf("获取相簿列表失败: %s\n", err) fmt.Printf("获取相簿列表失败: %s\n", err)
return return
@@ -326,7 +326,7 @@ func RunAlbumCreate(name, description string) {
} }
activeUser := GetActiveUser() activeUser := GetActiveUser()
_, err := activeUser.PanClient().AlbumCreate(&aliyunpan.AlbumCreateParam{ _, err := activeUser.PanClient().WebapiPanClient().AlbumCreate(&aliyunpan.AlbumCreateParam{
Name: name, Name: name,
Description: description, Description: description,
}) })
@@ -344,7 +344,7 @@ func RunAlbumDelete(nameList []string) {
} }
activeUser := GetActiveUser() activeUser := GetActiveUser()
records, err := activeUser.PanClient().AlbumListGetAll(&aliyunpan.AlbumListParam{}) records, err := activeUser.PanClient().WebapiPanClient().AlbumListGetAll(&aliyunpan.AlbumListParam{})
if err != nil { if err != nil {
fmt.Printf("获取相簿列表失败: %s\n", err) fmt.Printf("获取相簿列表失败: %s\n", err)
return return
@@ -354,7 +354,7 @@ func RunAlbumDelete(nameList []string) {
for i, name := range nameList { for i, name := range nameList {
if name == record.Name { if name == record.Name {
nameList = append(nameList[:i], nameList[i+1:]...) nameList = append(nameList[:i], nameList[i+1:]...)
_, err := activeUser.PanClient().AlbumDelete(&aliyunpan.AlbumDeleteParam{ _, err := activeUser.PanClient().WebapiPanClient().AlbumDelete(&aliyunpan.AlbumDeleteParam{
AlbumId: record.AlbumId, AlbumId: record.AlbumId,
}) })
if err != nil { if err != nil {
@@ -370,7 +370,7 @@ func RunAlbumDelete(nameList []string) {
} }
func getAlbumFromName(activeUser *config.PanUser, name string) *aliyunpan.AlbumEntity { func getAlbumFromName(activeUser *config.PanUser, name string) *aliyunpan.AlbumEntity {
records, err := activeUser.PanClient().AlbumListGetAll(&aliyunpan.AlbumListParam{}) records, err := activeUser.PanClient().WebapiPanClient().AlbumListGetAll(&aliyunpan.AlbumListParam{})
if err != nil { if err != nil {
fmt.Printf("获取相簿列表失败: %s\n", err) fmt.Printf("获取相簿列表失败: %s\n", err)
return nil return nil
@@ -399,7 +399,7 @@ func RunAlbumRename(name, newName string) {
if record == nil { if record == nil {
return return
} }
_, err := activeUser.PanClient().AlbumEdit(&aliyunpan.AlbumEditParam{ _, err := activeUser.PanClient().WebapiPanClient().AlbumEdit(&aliyunpan.AlbumEditParam{
AlbumId: record.AlbumId, AlbumId: record.AlbumId,
Description: record.Description, Description: record.Description,
Name: newName, Name: newName,
@@ -424,7 +424,7 @@ func RunAlbumListFile(name string) {
return return
} }
fileList, er := activeUser.PanClient().AlbumListFileGetAll(&aliyunpan.AlbumListFileParam{ fileList, er := activeUser.PanClient().WebapiPanClient().AlbumListFileGetAll(&aliyunpan.AlbumListFileParam{
AlbumId: record.AlbumId, AlbumId: record.AlbumId,
}) })
if er != nil { if er != nil {
@@ -450,7 +450,7 @@ func RunAlbumRmFile(name string, nameList []string) {
return return
} }
fileList, er := activeUser.PanClient().AlbumListFileGetAll(&aliyunpan.AlbumListFileParam{ fileList, er := activeUser.PanClient().WebapiPanClient().AlbumListFileGetAll(&aliyunpan.AlbumListFileParam{
AlbumId: album.AlbumId, AlbumId: album.AlbumId,
}) })
if er != nil { if er != nil {
@@ -480,7 +480,7 @@ func RunAlbumRmFile(name string, nameList []string) {
return return
} }
// delete file // delete file
_, e := activeUser.PanClient().AlbumDeleteFile(param) _, e := activeUser.PanClient().WebapiPanClient().AlbumDeleteFile(param)
if e != nil { if e != nil {
fmt.Printf("删除相簿文件失败:%s\n", e) fmt.Printf("删除相簿文件失败:%s\n", e)
return return
@@ -519,7 +519,7 @@ func RunAlbumAddFile(albumName string, filePathList []string, filterOption Album
} }
for k := range paths { for k := range paths {
filePath := paths[k] filePath := paths[k]
fileInfo, apierr := activeUser.PanClient().FileInfoByPath(activeUser.ActiveDriveId, filePath) fileInfo, apierr := activeUser.PanClient().WebapiPanClient().FileInfoByPath(activeUser.ActiveDriveId, filePath)
if apierr != nil { if apierr != nil {
fmt.Printf("获取文件信息失败: %s\n", filePath) fmt.Printf("获取文件信息失败: %s\n", filePath)
continue continue
@@ -531,7 +531,7 @@ func RunAlbumAddFile(albumName string, filePathList []string, filterOption Album
} }
} else { } else {
// folder // folder
activeUser.PanClient().FilesDirectoriesRecurseList(activeUser.ActiveDriveId, fileInfo.Path, func(depth int, _ string, fd *aliyunpan.FileEntity, apiError *apierror.ApiError) bool { activeUser.PanClient().WebapiPanClient().FilesDirectoriesRecurseList(activeUser.ActiveDriveId, fileInfo.Path, func(depth int, _ string, fd *aliyunpan.FileEntity, apiError *apierror.ApiError) bool {
if apiError != nil { if apiError != nil {
logger.Verbosef("%s\n", apiError) logger.Verbosef("%s\n", apiError)
return true return true
@@ -553,7 +553,7 @@ func RunAlbumAddFile(albumName string, filePathList []string, filterOption Album
return return
} }
// add file // add file
_, e := activeUser.PanClient().AlbumAddFile(param) _, e := activeUser.PanClient().WebapiPanClient().AlbumAddFile(param)
if e != nil { if e != nil {
fmt.Printf("增加相簿文件失败:%s\n", e) fmt.Printf("增加相簿文件失败:%s\n", e)
return return
@@ -584,9 +584,9 @@ func RunAlbumDownloadFile(albumNames []string, options *DownloadOptions) {
} }
activeUser := GetActiveUser() activeUser := GetActiveUser()
activeUser.PanClient().EnableCache() activeUser.PanClient().WebapiPanClient().EnableCache()
activeUser.PanClient().ClearCache() activeUser.PanClient().WebapiPanClient().ClearCache()
defer activeUser.PanClient().DisableCache() defer activeUser.PanClient().WebapiPanClient().DisableCache()
// pan token expired checker // pan token expired checker
continueFlag := int32(0) continueFlag := int32(0)
atomic.StoreInt32(&continueFlag, 0) atomic.StoreInt32(&continueFlag, 0)
@@ -681,7 +681,7 @@ func RunAlbumDownloadFile(albumNames []string, options *DownloadOptions) {
continue continue
} }
// 获取相簿下的所有文件 // 获取相簿下的所有文件
fileList, er := activeUser.PanClient().AlbumListFileGetAll(&aliyunpan.AlbumListFileParam{ fileList, er := activeUser.PanClient().WebapiPanClient().AlbumListFileGetAll(&aliyunpan.AlbumListFileParam{
AlbumId: record.AlbumId, AlbumId: record.AlbumId,
}) })
if er != nil { if er != nil {
@@ -700,7 +700,7 @@ func RunAlbumDownloadFile(albumNames []string, options *DownloadOptions) {
newCfg := *cfg newCfg := *cfg
unit := pandownload.DownloadTaskUnit{ unit := pandownload.DownloadTaskUnit{
Cfg: &newCfg, // 复制一份新的cfg Cfg: &newCfg, // 复制一份新的cfg
PanClient: panClient, PanClient: panClient.WebapiPanClient(),
VerbosePrinter: panCommandVerbose, VerbosePrinter: panCommandVerbose,
PrintFormat: downloadPrintFormat(options.Load), PrintFormat: downloadPrintFormat(options.Load),
ParentTaskExecutor: &executor, ParentTaskExecutor: &executor,
+1 -1
View File
@@ -96,7 +96,7 @@ func RunChangeDirectory(driveId, targetPath string) {
user := config.Config.ActiveUser() user := config.Config.ActiveUser()
targetPath = user.PathJoin(driveId, targetPath) targetPath = user.PathJoin(driveId, targetPath)
//targetPathInfo, err := user.PanClient().FileInfoByPath(driveId, targetPath) //targetPathInfo, err := user.PanClient().WebapiPanClient().FileInfoByPath(driveId, targetPath)
files, err := matchPathByShellPattern(driveId, targetPath) files, err := matchPathByShellPattern(driveId, targetPath)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
+1 -1
View File
@@ -58,7 +58,7 @@ const (
var ErrBadArgs = errors.New("参数错误") var ErrBadArgs = errors.New("参数错误")
var ErrNotLogined = errors.New("未登录账号") var ErrNotLogined = errors.New("未登录账号")
func GetActivePanClient() *aliyunpan.PanClient { func GetActivePanClient() *config.PanClient {
return config.Config.ActiveUser().PanClient() return config.Config.ActiveUser().PanClient()
} }
+4 -4
View File
@@ -219,9 +219,9 @@ func downloadPrintFormat(load int) string {
// RunDownload 执行下载网盘内文件 // RunDownload 执行下载网盘内文件
func RunDownload(paths []string, options *DownloadOptions) { func RunDownload(paths []string, options *DownloadOptions) {
activeUser := GetActiveUser() activeUser := GetActiveUser()
activeUser.PanClient().EnableCache() activeUser.PanClient().WebapiPanClient().EnableCache()
activeUser.PanClient().ClearCache() activeUser.PanClient().WebapiPanClient().ClearCache()
defer activeUser.PanClient().DisableCache() defer activeUser.PanClient().WebapiPanClient().DisableCache()
// pan token expired checker // pan token expired checker
continueFlag := int32(0) continueFlag := int32(0)
atomic.StoreInt32(&continueFlag, 0) atomic.StoreInt32(&continueFlag, 0)
@@ -347,7 +347,7 @@ func RunDownload(paths []string, options *DownloadOptions) {
// 匹配的文件 // 匹配的文件
unit := pandownload.DownloadTaskUnit{ unit := pandownload.DownloadTaskUnit{
Cfg: &newCfg, // 复制一份新的cfg Cfg: &newCfg, // 复制一份新的cfg
PanClient: panClient, PanClient: panClient.WebapiPanClient(),
VerbosePrinter: panCommandVerbose, VerbosePrinter: panCommandVerbose,
PrintFormat: downloadPrintFormat(options.Load), PrintFormat: downloadPrintFormat(options.Load),
ParentTaskExecutor: &executor, ParentTaskExecutor: &executor,
+2 -2
View File
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // http://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
@@ -117,7 +117,7 @@ func RunExportFiles(driveId string, overwrite bool, panPaths []string, saveLocal
for _, panPath := range panPaths { for _, panPath := range panPaths {
panPath = activeUser.PathJoin(driveId, panPath) panPath = activeUser.PathJoin(driveId, panPath)
panClient.FilesDirectoriesRecurseList(driveId, panPath, func(depth int, _ string, fd *aliyunpan.FileEntity, apiError *apierror.ApiError) bool { panClient.WebapiPanClient().FilesDirectoriesRecurseList(driveId, panPath, func(depth int, _ string, fd *aliyunpan.FileEntity, apiError *apierror.ApiError) bool {
if apiError != nil { if apiError != nil {
logger.Verbosef("%s\n", apiError) logger.Verbosef("%s\n", apiError)
return true return true
+5 -5
View File
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // http://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
@@ -199,7 +199,7 @@ func processOneImport(driveId string, isOverwrite bool, dirMap map[string]*dirFi
} }
if efi != nil && efi.FileId != "" { if efi != nil && efi.FileId != "" {
// existed, delete it // existed, delete it
fdr, err := panClient.FileDelete([]*aliyunpan.FileBatchActionParam{ fdr, err := panClient.WebapiPanClient().FileDelete([]*aliyunpan.FileBatchActionParam{
{ {
DriveId: driveId, DriveId: driveId,
FileId: efi.FileId, FileId: efi.FileId,
@@ -221,7 +221,7 @@ func processOneImport(driveId string, isOverwrite bool, dirMap map[string]*dirFi
ContentHash: item.FileSha1, ContentHash: item.FileSha1,
ParentFileId: dataItem.Dir.FileId, ParentFileId: dataItem.Dir.FileId,
} }
uploadOpEntity, apierr := panClient.CreateUploadFile(appCreateUploadFileParam) uploadOpEntity, apierr := panClient.WebapiPanClient().CreateUploadFile(appCreateUploadFileParam)
if apierr != nil { if apierr != nil {
fmt.Println("创建秒传任务失败:" + apierr.Error()) fmt.Println("创建秒传任务失败:" + apierr.Error())
return false, true return false, true
@@ -247,7 +247,7 @@ func prepareMkdir(driveId string, importFileItems []RapidUploadItem) map[string]
continue continue
} }
if panDir != "/" { if panDir != "/" {
rs, apierr = panClient.MkdirRecursive(driveId, "", "", 0, strings.Split(path.Clean(panDir), "/")) rs, apierr = panClient.WebapiPanClient().MkdirRecursive(driveId, "", "", 0, strings.Split(path.Clean(panDir), "/"))
if apierr != nil || rs.FileId == "" { if apierr != nil || rs.FileId == "" {
logger.Verboseln("创建云盘文件夹失败") logger.Verboseln("创建云盘文件夹失败")
continue continue
@@ -263,7 +263,7 @@ func prepareMkdir(driveId string, importFileItems []RapidUploadItem) map[string]
param := &aliyunpan.FileListParam{} param := &aliyunpan.FileListParam{}
param.DriveId = driveId param.DriveId = driveId
param.ParentFileId = rs.FileId param.ParentFileId = rs.FileId
allFileInfo, err1 := panClient.FileListGetAll(param, 0) allFileInfo, err1 := panClient.WebapiPanClient().FileListGetAll(param, 0)
if err1 != nil { if err1 != nil {
logger.Verboseln("获取文件信息出错") logger.Verboseln("获取文件信息出错")
continue continue
+7 -7
View File
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // http://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
@@ -80,9 +80,9 @@ func CmdLocateUrl() cli.Command {
func RunLocateUrl(driveId string, paths []string, saveFilePath string) { func RunLocateUrl(driveId string, paths []string, saveFilePath string) {
useInternalUrl := config.Config.TransferUrlType == 2 useInternalUrl := config.Config.TransferUrlType == 2
activeUser := GetActiveUser() activeUser := GetActiveUser()
activeUser.PanClient().EnableCache() activeUser.PanClient().WebapiPanClient().EnableCache()
activeUser.PanClient().ClearCache() activeUser.PanClient().WebapiPanClient().ClearCache()
defer activeUser.PanClient().DisableCache() defer activeUser.PanClient().WebapiPanClient().DisableCache()
paths, err := makePathAbsolute(driveId, paths...) paths, err := makePathAbsolute(driveId, paths...)
if err != nil { if err != nil {
@@ -116,7 +116,7 @@ func RunLocateUrl(driveId string, paths []string, saveFilePath string) {
} }
fileInfo := item.(*aliyunpan.FileEntity) fileInfo := item.(*aliyunpan.FileEntity)
if fileInfo.IsFolder() { // 文件夹,获取下面所有文件 if fileInfo.IsFolder() { // 文件夹,获取下面所有文件
allFilesInFolder, er := activeUser.PanClient().FileListGetAll(&aliyunpan.FileListParam{ allFilesInFolder, er := activeUser.PanClient().WebapiPanClient().FileListGetAll(&aliyunpan.FileListParam{
DriveId: driveId, DriveId: driveId,
ParentFileId: fileInfo.FileId, ParentFileId: fileInfo.FileId,
}, 300) }, 300)
@@ -131,7 +131,7 @@ func RunLocateUrl(driveId string, paths []string, saveFilePath string) {
fileEntityQueue.Push(f) fileEntityQueue.Push(f)
continue continue
} }
durl, apierr := activeUser.PanClient().GetFileDownloadUrl(&aliyunpan.GetFileDownloadUrlParam{ durl, apierr := activeUser.PanClient().WebapiPanClient().GetFileDownloadUrl(&aliyunpan.GetFileDownloadUrlParam{
DriveId: driveId, DriveId: driveId,
FileId: f.FileId, FileId: f.FileId,
}) })
@@ -151,7 +151,7 @@ func RunLocateUrl(driveId string, paths []string, saveFilePath string) {
} }
} }
} else { // 文件 } else { // 文件
durl, apierr := activeUser.PanClient().GetFileDownloadUrl(&aliyunpan.GetFileDownloadUrlParam{ durl, apierr := activeUser.PanClient().WebapiPanClient().GetFileDownloadUrl(&aliyunpan.GetFileDownloadUrlParam{
DriveId: driveId, DriveId: driveId,
FileId: fileInfo.FileId, FileId: fileInfo.FileId,
}) })
+43 -79
View File
@@ -15,14 +15,12 @@ package command
import ( import (
"fmt" "fmt"
"github.com/tickstep/aliyunpan-api/aliyunpan"
"github.com/tickstep/aliyunpan/cmder/cmdliner" "github.com/tickstep/aliyunpan/cmder/cmdliner"
"github.com/tickstep/aliyunpan/internal/config" "github.com/tickstep/aliyunpan/internal/config"
"github.com/tickstep/aliyunpan/internal/functions/panlogin" "github.com/tickstep/aliyunpan/internal/functions/panlogin"
"github.com/tickstep/library-go/logger"
_ "github.com/tickstep/library-go/requester" _ "github.com/tickstep/library-go/requester"
"github.com/urfave/cli" "github.com/urfave/cli"
"time" "strings"
) )
func CmdLogin() cli.Command { func CmdLogin() cli.Command {
@@ -34,55 +32,36 @@ func CmdLogin() cli.Command {
1.常规登录,按提示一步一步来即可 1.常规登录,按提示一步一步来即可
aliyunpan login aliyunpan login
2.直接指定RefreshToken进行登录
aliyunpan login -RefreshToken=8B12CBBCE89CA8DFC3445985B63B511B5E7EC7...
3.使用二维码方式进行登录
aliyunpan login -QrCode
`, `,
Category: "阿里云盘账号", Category: "阿里云盘账号",
Before: ReloadConfigFunc, // 每次进行登录动作的时候需要调用刷新配置 Before: ReloadConfigFunc, // 每次进行登录动作的时候需要调用刷新配置
After: SaveConfigFunc, // 登录完成需要调用保存配置 After: SaveConfigFunc, // 登录完成需要调用保存配置
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
refreshTokenStr := "" ticketId := ""
if refreshTokenStr == "" { openToken := &config.PanClientToken{}
refreshTokenStr = c.String("RefreshToken") webToken := &config.PanClientToken{}
}
useQrCode := c.Bool("QrCode")
tokenId := ""
webToken := aliyunpan.WebLoginToken{}
refreshToken := ""
var err error var err error
tokenId, refreshToken, webToken, err = RunLogin(useQrCode, refreshTokenStr) ticketId, openToken, webToken, err = RunLogin()
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return err return err
} }
cloudUser, err := config.SetupUserByCookie(&webToken, config.Config.DeviceId, config.Config.DeviceName) cloudUser, err := config.SetupUserByCookie(openToken, webToken,
ticketId, "",
config.Config.DeviceId, config.Config.DeviceName,
config.Config.ClientId, config.Config.ClientSecret)
if cloudUser == nil { if cloudUser == nil {
fmt.Println("登录失败: ", err) fmt.Println("登录失败: ", err)
return nil return nil
} }
cloudUser.RefreshToken = refreshToken cloudUser.TicketId = ticketId
cloudUser.TokenId = tokenId
config.Config.SetActiveUser(cloudUser) config.Config.SetActiveUser(cloudUser)
fmt.Println("阿里云盘登录成功: ", cloudUser.Nickname) fmt.Println("阿里云盘登录成功: ", cloudUser.Nickname)
return nil return nil
}, },
// 命令的附加options参数说明,使用 help panlogin 命令即可查看 // 命令的附加options参数说明,使用 help panlogin 命令即可查看
Flags: []cli.Flag{ Flags: []cli.Flag{},
// aliyunpan panlogin -RefreshToken=8B12CBBCE89CA8DFC3445985B63B511B5E7EC7...
cli.StringFlag{
Name: "RefreshToken",
Usage: "使用RefreshToken Cookie来登录帐号",
},
cli.BoolFlag{
Name: "QrCode",
Usage: "使用二维码登录",
},
},
} }
} }
@@ -117,7 +96,7 @@ func CmdLogout() cli.Command {
} }
// 云端注销登录 // 云端注销登录
//if _, e := activeUser.PanClient().DeviceLogout(); e != nil { //if _, e := activeUser.PanClient().WebapiPanClient().DeviceLogout(); e != nil {
// fmt.Printf("登出设备失败,请手动在网页端进行登出: %s\n", e.String()) // fmt.Printf("登出设备失败,请手动在网页端进行登出: %s\n", e.String())
//} //}
@@ -139,55 +118,40 @@ func CmdLogout() cli.Command {
} }
} }
func RunLogin(useQrCodeLogin bool, refreshToken string) (tokenId, refreshTokenStr string, webToken aliyunpan.WebLoginToken, error error) { func RunLogin() (ticketId string, openapiToken, webapiToken *config.PanClientToken, error error) {
if useQrCodeLogin { h := panlogin.NewLoginHelper(config.DefaultTokenServiceWebHost)
h := panlogin.NewLoginHelper(config.DefaultTokenServiceWebHost)
qrCodeUrlResult, err := h.GetQRCodeLoginUrl("")
if err != nil {
fmt.Println("二维码登录错误:", err)
return "", "", aliyunpan.WebLoginToken{}, err
}
fmt.Printf("请在浏览器打开以下链接进行扫码登录,链接有效时间为5分钟\n%s\n\n", qrCodeUrlResult.TokenUrl+"&deviceId="+config.Config.DeviceId)
// handler waiting // web login request
line := cmdliner.NewLiner() qrCodeUrlResult, err := h.GetQRCodeLoginUrl("")
var qrCodeLoginResult *panlogin.QRCodeLoginResult if err != nil {
queryResult := true fmt.Println("登录出错:", err)
defer line.Close() return "", nil, nil, err
}
ticketId = qrCodeUrlResult.TokenId
loginUrl := &strings.Builder{}
fmt.Fprintf(loginUrl, "https://openapi.alipan.com/oauth/authorize?client_id=%s&redirect_uri=https%%3A%%2F%%2Fapi.tickstep.com%%2Fauth%%2Ftickstep%%2Faliyunpan%%2Ftoken%%2Fopenapi%%2F%s%%2Fauth&scope=user:base,file:all:read,file:all:write",
config.Config.ClientId, ticketId)
fmt.Printf("请在浏览器打开以下链接进行扫码登录,链接有效时间为5分钟\n%s\n\n", loginUrl)
go func() { // handler waiting
for queryResult { line := cmdliner.NewLiner()
time.Sleep(3 * time.Second) defer line.Close()
qr, er := h.GetQRCodeLoginResult(qrCodeUrlResult.TokenId) line.State.Prompt("请在浏览器里面完成扫码登录,然后再按Enter键继续...")
if er != nil {
continue
}
logger.Verboseln(qr)
if qr.QrCodeStatus == "CONFIRMED" {
// login successfully
qrCodeLoginResult = qr
break
} else if qr.QrCodeStatus == "EXPIRED" {
break
}
}
}()
line.State.Prompt("请在浏览器里面完成扫码登录,然后再按Enter键继续...") // get login token
if qrCodeLoginResult == nil { comToken, er := h.GetLoginToken(ticketId)
queryResult = false if er != nil {
return "", "", aliyunpan.WebLoginToken{}, fmt.Errorf("二维码登录失败") return ticketId, nil, nil, fmt.Errorf("登录失败,请稍后尝试重新登录")
}
tokenStr, er := h.ParseSecureRefreshToken("", qrCodeLoginResult.SecureRefreshToken)
if er != nil {
fmt.Println("解析Token错误:", er)
return "", "", aliyunpan.WebLoginToken{}, er
}
refreshToken = tokenStr
tokenId = qrCodeUrlResult.TokenId
} }
refreshTokenStr, webToken, error = DoLoginHelper(refreshToken) return ticketId,
return &config.PanClientToken{
AccessToken: comToken.Openapi.AccessToken,
Expired: comToken.Openapi.Expired,
},
&config.PanClientToken{
AccessToken: comToken.Webapi.AccessToken,
Expired: comToken.Webapi.Expired,
},
nil
} }
+2 -2
View File
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // http://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
@@ -169,7 +169,7 @@ func RunLs(driveId, targetPath string, lsOptions *LsOptions,
fileListParam.OrderBy = orderBy fileListParam.OrderBy = orderBy
fileListParam.OrderDirection = orderDirection fileListParam.OrderDirection = orderDirection
if targetPathInfo.IsFolder() { if targetPathInfo.IsFolder() {
fileResult, err1 := activeUser.PanClient().FileListGetAll(fileListParam, 200) fileResult, err1 := activeUser.PanClient().WebapiPanClient().FileListGetAll(fileListParam, 200)
if err1 != nil { if err1 != nil {
fmt.Println(err1) fmt.Println(err1)
return return
+2 -2
View File
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // http://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
@@ -56,7 +56,7 @@ func RunMkdir(driveId, name string) {
fullpath := activeUser.PathJoin(driveId, name) fullpath := activeUser.PathJoin(driveId, name)
rs := &aliyunpan.MkdirResult{} rs := &aliyunpan.MkdirResult{}
err := apierror.NewFailedApiError("") err := apierror.NewFailedApiError("")
rs, err = activeUser.PanClient().Mkdir(driveId, "", fullpath) rs, err = activeUser.PanClient().WebapiPanClient().Mkdir(driveId, "", fullpath)
if err != nil { if err != nil {
fmt.Println("创建文件夹失败:" + err.Error()) fmt.Println("创建文件夹失败:" + err.Error())
+2 -2
View File
@@ -98,7 +98,7 @@ func RunMove(driveId string, paths ...string) {
}) })
cacheCleanPaths = append(cacheCleanPaths, path.Dir(mfi.Path)) cacheCleanPaths = append(cacheCleanPaths, path.Dir(mfi.Path))
} }
fmr, er := activeUser.PanClient().FileMove(moveFileParamList) fmr, er := activeUser.PanClient().WebapiPanClient().FileMove(moveFileParamList)
for _, rs := range fmr { for _, rs := range fmr {
if !rs.Success { if !rs.Success {
@@ -138,7 +138,7 @@ func getFileInfo(driveId string, paths ...string) (opFileList []*aliyunpan.FileE
// the last one is the target file path // the last one is the target file path
targetFilePath := path.Clean(paths[len(paths)-1]) targetFilePath := path.Clean(paths[len(paths)-1])
absolutePath := activeUser.PathJoin(driveId, targetFilePath) absolutePath := activeUser.PathJoin(driveId, targetFilePath)
targetFile, err := activeUser.PanClient().FileInfoByPath(driveId, absolutePath) targetFile, err := activeUser.PanClient().WebapiPanClient().FileInfoByPath(driveId, absolutePath)
if err != nil || !targetFile.IsFolder() { if err != nil || !targetFile.IsFolder() {
return nil, nil, nil, fmt.Errorf("指定目标文件夹不存在") return nil, nil, nil, fmt.Errorf("指定目标文件夹不存在")
} }
+1 -1
View File
@@ -52,7 +52,7 @@ func CmdQuota() cli.Command {
} }
func RunGetQuotaInfo() (quotaInfo *QuotaInfo, error error) { func RunGetQuotaInfo() (quotaInfo *QuotaInfo, error error) {
user, err := GetActivePanClient().GetUserInfo() user, err := GetActivePanClient().WebapiPanClient().GetUserInfo()
if err != nil { if err != nil {
return nil, err return nil, err
} }
+5 -5
View File
@@ -132,7 +132,7 @@ func CmdRecycle() cli.Command {
// RunRecycleList 执行列出回收站文件列表 // RunRecycleList 执行列出回收站文件列表
func RunRecycleList(driveId string) { func RunRecycleList(driveId string) {
panClient := GetActivePanClient() panClient := GetActivePanClient()
fdl, err := panClient.RecycleBinFileListGetAll(&aliyunpan.RecycleBinFileListParam{ fdl, err := panClient.WebapiPanClient().RecycleBinFileListGetAll(&aliyunpan.RecycleBinFileListParam{
DriveId: driveId, DriveId: driveId,
Limit: 100, Limit: 100,
}) })
@@ -174,7 +174,7 @@ func RunRecycleRestore(driveId string, fidStrList ...string) {
return return
} }
rbfr, err := panClient.RecycleBinFileRestore(restoreFileList) rbfr, err := panClient.WebapiPanClient().RecycleBinFileRestore(restoreFileList)
if rbfr != nil && len(rbfr) > 0 { if rbfr != nil && len(rbfr) > 0 {
fmt.Printf("还原文件成功\n") fmt.Printf("还原文件成功\n")
return return
@@ -203,7 +203,7 @@ func RunRecycleDelete(driveId string, fidStrList ...string) {
return return
} }
rbfr, err := panClient.RecycleBinFileDelete(deleteFileList) rbfr, err := panClient.WebapiPanClient().RecycleBinFileDelete(deleteFileList)
if rbfr != nil && len(rbfr) > 0 { if rbfr != nil && len(rbfr) > 0 {
fmt.Printf("彻底删除文件成功\n") fmt.Printf("彻底删除文件成功\n")
return return
@@ -220,7 +220,7 @@ func RunRecycleClear(driveId string) {
panClient := GetActivePanClient() panClient := GetActivePanClient()
// 提交清空回收站异步任务 // 提交清空回收站异步任务
r, err := panClient.RecycleBinFileClear(&aliyunpan.RecycleBinFileClearParam{ r, err := panClient.WebapiPanClient().RecycleBinFileClear(&aliyunpan.RecycleBinFileClearParam{
DriveId: driveId, DriveId: driveId,
}) })
if err != nil { if err != nil {
@@ -229,7 +229,7 @@ func RunRecycleClear(driveId string) {
} }
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
ar, err1 := panClient.AsyncTaskQueryStatus(&aliyunpan.AsyncTaskQueryStatusParam{ ar, err1 := panClient.WebapiPanClient().AsyncTaskQueryStatus(&aliyunpan.AsyncTaskQueryStatusParam{
AsyncTaskId: r.AsyncTaskId, AsyncTaskId: r.AsyncTaskId,
}) })
if err1 != nil { if err1 != nil {
+4 -4
View File
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // http://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
@@ -136,14 +136,14 @@ func RunRename(driveId string, oldName string, newName string) {
} }
fileId := "" fileId := ""
r, err := GetActivePanClient().FileInfoByPath(driveId, activeUser.PathJoin(driveId, oldName)) r, err := GetActivePanClient().WebapiPanClient().FileInfoByPath(driveId, activeUser.PathJoin(driveId, oldName))
if err != nil { if err != nil {
fmt.Printf("原文件不存在: %s, %s\n", oldName, err) fmt.Printf("原文件不存在: %s, %s\n", oldName, err)
return return
} }
fileId = r.FileId fileId = r.FileId
b, e := activeUser.PanClient().FileRename(driveId, fileId, path.Base(newName)) b, e := activeUser.PanClient().WebapiPanClient().FileRename(driveId, fileId, path.Base(newName))
if e != nil { if e != nil {
fmt.Println(e.Err) fmt.Println(e.Err)
return return
@@ -234,7 +234,7 @@ func RunRenameBatch(skipConfirm bool, driveId string, expression, replacement, f
// 重命名 // 重命名
for _, file := range files { for _, file := range files {
b, e := activeUser.PanClient().FileRename(driveId, file.file.FileId, file.newFileName) b, e := activeUser.PanClient().WebapiPanClient().FileRename(driveId, file.file.FileId, file.newFileName)
if e != nil { if e != nil {
fmt.Println(e.Err) fmt.Println(e.Err)
return return
+2 -2
View File
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // http://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
@@ -106,7 +106,7 @@ func RunRemove(driveId string, paths ...string) {
// delete // delete
successDelFileEntity := []*aliyunpan.FileEntity{} successDelFileEntity := []*aliyunpan.FileEntity{}
fdr, err := activeUser.PanClient().FileDelete(delFileInfos) fdr, err := activeUser.PanClient().WebapiPanClient().FileDelete(delFileInfos)
if fdr != nil { if fdr != nil {
for _, item := range fdr { for _, item := range fdr {
if !item.Success { if !item.Success {
+6 -6
View File
@@ -72,7 +72,7 @@ func RunSave(driveId string, args ...string) {
targetFilePath := path.Clean(args[len(args)-1]) targetFilePath := path.Clean(args[len(args)-1])
absolutePath := activeUser.PathJoin(driveId, targetFilePath) absolutePath := activeUser.PathJoin(driveId, targetFilePath)
targetFile, err := activeUser.PanClient().FileInfoByPath(driveId, absolutePath) targetFile, err := activeUser.PanClient().WebapiPanClient().FileInfoByPath(driveId, absolutePath)
if err != nil || !targetFile.IsFolder() { if err != nil || !targetFile.IsFolder() {
fmt.Println("指定目标文件夹不存在") fmt.Println("指定目标文件夹不存在")
return return
@@ -88,19 +88,19 @@ func RunSave(driveId string, args ...string) {
sharePwd = args[1] sharePwd = args[1]
} }
token, err := activeUser.PanClient().GetShareToken(shareID, sharePwd) token, err := activeUser.PanClient().WebapiPanClient().GetShareToken(shareID, sharePwd)
if err != nil { if err != nil {
fmt.Println("读取分享链接失败:", err) fmt.Println("读取分享链接失败:", err)
return return
} }
list, err := activeUser.PanClient().GetListByShare(token.ShareToken, shareID, "") list, err := activeUser.PanClient().WebapiPanClient().GetListByShare(token.ShareToken, shareID, "")
if err != nil { if err != nil {
fmt.Println("读取分享文件列表失败:", err) fmt.Println("读取分享文件列表失败:", err)
return return
} }
for list.NextMarker != "" { for list.NextMarker != "" {
list2, err := activeUser.PanClient().GetListByShare(token.ShareToken, shareID, "") list2, err := activeUser.PanClient().WebapiPanClient().GetListByShare(token.ShareToken, shareID, "")
if err != nil { if err != nil {
fmt.Println("读取分享文件列表失败:", err) fmt.Println("读取分享文件列表失败:", err)
return return
@@ -129,7 +129,7 @@ func RunSave(driveId string, args ...string) {
} }
fmt.Println() fmt.Println()
result, err := activeUser.PanClient().FileCopy(token.ShareToken, params) result, err := activeUser.PanClient().WebapiPanClient().FileCopy(token.ShareToken, params)
if err != nil { if err != nil {
fmt.Println("保存分享文件失败:", err) fmt.Println("保存分享文件失败:", err)
return return
@@ -148,7 +148,7 @@ func RunSave(driveId string, args ...string) {
} }
} }
if ids != nil { if ids != nil {
result2, err := activeUser.PanClient().AsyncTaskGet(token.ShareToken, ids) result2, err := activeUser.PanClient().WebapiPanClient().AsyncTaskGet(token.ShareToken, ids)
if err != nil { if err != nil {
fmt.Println("读取保存结果失败:", err) fmt.Println("读取保存结果失败:", err)
} }
+6 -6
View File
@@ -286,7 +286,7 @@ func RunShareSet(modeFlag, driveId string, paths []string, expiredTime string, s
if modeFlag == "3" { if modeFlag == "3" {
// 快传 // 快传
r, err1 := panClient.FastShareLinkCreate(aliyunpan.FastShareCreateParam{ r, err1 := panClient.WebapiPanClient().FastShareLinkCreate(aliyunpan.FastShareCreateParam{
DriveId: driveId, DriveId: driveId,
FileIdList: fidList, FileIdList: fidList,
}) })
@@ -303,7 +303,7 @@ func RunShareSet(modeFlag, driveId string, paths []string, expiredTime string, s
fmt.Printf("链接:%s\n", r.ShareUrl) fmt.Printf("链接:%s\n", r.ShareUrl)
} else { } else {
// 分享 // 分享
r, err1 := panClient.ShareLinkCreate(aliyunpan.ShareCreateParam{ r, err1 := panClient.WebapiPanClient().ShareLinkCreate(aliyunpan.ShareCreateParam{
DriveId: driveId, DriveId: driveId,
SharePwd: sharePwd, SharePwd: sharePwd,
Expiration: expiredTime, Expiration: expiredTime,
@@ -330,7 +330,7 @@ func RunShareSet(modeFlag, driveId string, paths []string, expiredTime string, s
// RunShareList 执行列出分享列表 // RunShareList 执行列出分享列表
func RunShareList() { func RunShareList() {
activeUser := GetActiveUser() activeUser := GetActiveUser()
records, err := activeUser.PanClient().ShareLinkList(activeUser.UserId) records, err := activeUser.PanClient().WebapiPanClient().ShareLinkList(activeUser.UserId)
if err != nil { if err != nil {
fmt.Printf("获取分享列表失败: %s\n", err) fmt.Printf("获取分享列表失败: %s\n", err)
return return
@@ -378,7 +378,7 @@ func RunShareCancel(shareIdList []string) {
} }
activeUser := GetActiveUser() activeUser := GetActiveUser()
r, err := activeUser.PanClient().ShareLinkCancel(shareIdList) r, err := activeUser.PanClient().WebapiPanClient().ShareLinkCancel(shareIdList)
if err != nil { if err != nil {
fmt.Printf("取消分享操作失败: %s\n", err) fmt.Printf("取消分享操作失败: %s\n", err)
return return
@@ -393,7 +393,7 @@ func RunShareCancel(shareIdList []string) {
func RunShareExport(option, saveFilePath string) { func RunShareExport(option, saveFilePath string) {
activeUser := GetActiveUser() activeUser := GetActiveUser()
records, err := activeUser.PanClient().ShareLinkList(activeUser.UserId) records, err := activeUser.PanClient().WebapiPanClient().ShareLinkList(activeUser.UserId)
if err != nil { if err != nil {
fmt.Printf("获取分享列表失败: %s\n", err) fmt.Printf("获取分享列表失败: %s\n", err)
return return
@@ -467,7 +467,7 @@ func RunShareMc(driveId string, hideRelativePath bool, panPaths []string) {
totalCount := 0 totalCount := 0
for _, panPath := range panPaths { for _, panPath := range panPaths {
panPath = activeUser.PathJoin(driveId, panPath) panPath = activeUser.PathJoin(driveId, panPath)
panClient.FilesDirectoriesRecurseList(driveId, panPath, func(depth int, _ string, fd *aliyunpan.FileEntity, apiError *apierror.ApiError) bool { panClient.WebapiPanClient().FilesDirectoriesRecurseList(driveId, panPath, func(depth int, _ string, fd *aliyunpan.FileEntity, apiError *apierror.ApiError) bool {
if apiError != nil { if apiError != nil {
logger.Verbosef("%s\n", apiError) logger.Verbosef("%s\n", apiError)
return true return true
+7 -5
View File
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // http://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
@@ -18,6 +18,7 @@ import (
"github.com/tickstep/aliyunpan-api/aliyunpan" "github.com/tickstep/aliyunpan-api/aliyunpan"
"github.com/tickstep/aliyunpan/cmder" "github.com/tickstep/aliyunpan/cmder"
"github.com/tickstep/aliyunpan/internal/config" "github.com/tickstep/aliyunpan/internal/config"
"github.com/tickstep/aliyunpan/internal/global"
"github.com/tickstep/aliyunpan/internal/log" "github.com/tickstep/aliyunpan/internal/log"
"github.com/tickstep/aliyunpan/internal/syncdrive" "github.com/tickstep/aliyunpan/internal/syncdrive"
"github.com/tickstep/aliyunpan/internal/utils" "github.com/tickstep/aliyunpan/internal/utils"
@@ -302,7 +303,7 @@ func RunSync(defaultTask *syncdrive.SyncTask, fileDownloadParallel, fileUploadPa
maxUploadRate := config.Config.MaxUploadRate maxUploadRate := config.Config.MaxUploadRate
activeUser := GetActiveUser() activeUser := GetActiveUser()
panClient := activeUser.PanClient() panClient := activeUser.PanClient()
panClient.DisableCache() panClient.WebapiPanClient().DisableCache()
// pan token expired checker // pan token expired checker
continueFlag := int32(0) continueFlag := int32(0)
@@ -315,7 +316,8 @@ func RunSync(defaultTask *syncdrive.SyncTask, fileDownloadParallel, fileUploadPa
time.Sleep(time.Duration(1) * time.Minute) time.Sleep(time.Duration(1) * time.Minute)
if RefreshTokenInNeed(activeUser, config.Config.DeviceName) { if RefreshTokenInNeed(activeUser, config.Config.DeviceName) {
logger.Verboseln("update access token for sync task") logger.Verboseln("update access token for sync task")
panClient.UpdateToken(activeUser.WebToken) userWebToken := NewWebLoginToken(activeUser.WebapiToken.AccessToken, activeUser.WebapiToken.Expired)
panClient.WebapiPanClient().UpdateToken(userWebToken)
} }
} }
}(&continueFlag) }(&continueFlag)
@@ -354,7 +356,7 @@ func RunSync(defaultTask *syncdrive.SyncTask, fileDownloadParallel, fileUploadPa
LocalFileModifiedCheckIntervalSec: localDelayTime, LocalFileModifiedCheckIntervalSec: localDelayTime,
FileRecorder: fileRecorder, FileRecorder: fileRecorder,
} }
syncMgr := syncdrive.NewSyncTaskManager(activeUser, activeUser.DriveList.GetFileDriveId(), panClient, syncFolderRootPath, option) syncMgr := syncdrive.NewSyncTaskManager(activeUser, activeUser.DriveList.GetFileDriveId(), panClient.WebapiPanClient(), syncFolderRootPath, option)
syncConfigFile := syncMgr.ConfigFilePath() syncConfigFile := syncMgr.ConfigFilePath()
if tasks != nil { if tasks != nil {
syncConfigFile = "(使用命令行配置)" syncConfigFile = "(使用命令行配置)"
@@ -377,7 +379,7 @@ func RunSync(defaultTask *syncdrive.SyncTask, fileDownloadParallel, fileUploadPa
time.Sleep(60 * time.Second) time.Sleep(60 * time.Second)
} }
} else { } else {
if config.IsAppInCliMode { if global.IsAppInCliMode {
// in cmd mode // in cmd mode
c := "" c := ""
fmt.Println("本命令不会退出,如需要结束同步备份进程请输入y,然后按Enter键进行停止。") fmt.Println("本命令不会退出,如需要结束同步备份进程请输入y,然后按Enter键进行停止。")
-129
View File
@@ -1,129 +0,0 @@
// Copyright (c) 2020 tickstep.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package command
import (
"fmt"
"github.com/tickstep/aliyunpan-api/aliyunpan"
"github.com/tickstep/aliyunpan/cmder"
"github.com/tickstep/aliyunpan/internal/config"
"github.com/tickstep/aliyunpan/internal/plugins"
"github.com/tickstep/aliyunpan/internal/utils"
"github.com/tickstep/library-go/logger"
"github.com/urfave/cli"
)
func CmdToken() cli.Command {
return cli.Command{
Name: "token",
Usage: "Token相关操作",
UsageText: cmder.App().Name + " token",
Category: "阿里云盘账号",
Before: ReloadConfigFunc,
Action: func(c *cli.Context) error {
cli.ShowCommandHelp(c, c.Command.Name)
return nil
},
Subcommands: []cli.Command{
{
Name: "update",
Usage: "更新Token",
UsageText: cmder.App().Name + " token update",
Description: `
示例:
更新当前登录用户的Token
aliyunpan token update -mode 1
更新全部登录用户的Token
aliyunpan token update -mode 2
`,
Action: func(c *cli.Context) error {
if config.Config.ActiveUser() == nil {
fmt.Println("未登录账号,无需刷新Token")
return nil
}
modeFlag := "1"
if c.IsSet("mode") {
modeFlag = c.String("mode")
}
RunTokenUpdate(modeFlag)
return nil
},
Flags: []cli.Flag{
cli.StringFlag{
Name: "mode",
Usage: "模式,1-登录用户,2-全部用户",
Value: "1",
},
},
},
},
}
}
// RunTokenUpdate 执行Token更新
func RunTokenUpdate(modeFlag string) {
ReloadConfigFunc(nil)
// 获取当前插件
pluginManger := plugins.NewPluginManager(config.GetPluginDir())
plugin, _ := pluginManger.GetPlugin()
params := &plugins.UserTokenRefreshFinishParams{
Result: "success",
Message: "",
OldToken: "",
NewToken: "",
UpdatedAt: utils.NowTimeStr(),
}
userList := config.Config.UserList
if userList == nil || len(userList) == 0 {
fmt.Printf("没有登录用户,无需刷新Token\n")
return
}
for _, user := range userList {
params.Result = "success"
if modeFlag == "1" {
if user.UserId != config.Config.ActiveUID {
continue
}
}
newToken, e := aliyunpan.GetAccessTokenFromRefreshToken(user.RefreshToken)
if e != nil {
params.Result = "fail"
params.Message = e.Error()
fmt.Printf("无法为%s用户获取新的RefreshToken,可能需要重新登录\n", user.Nickname)
continue
}
if newToken != nil && newToken.RefreshToken != "" {
params.OldToken = user.RefreshToken
params.NewToken = newToken.RefreshToken
user.RefreshToken = newToken.RefreshToken
user.WebToken = *newToken
fmt.Printf("成功刷新%s用户的RefreshToken\n", user.Nickname)
} else {
params.Result = "fail"
}
// plugin callback
if er := plugin.UserTokenRefreshFinishCallback(plugins.GetContext(user), params); er != nil {
logger.Verbosef("UserTokenRefreshFinishCallback error: " + er.Error())
}
}
SaveConfigFunc(nil)
}
+4 -4
View File
@@ -146,7 +146,7 @@ func getTree(driveId, pathStr string, depth int, statistic *treeStatistic, setti
fileListParam.OrderBy = aliyunpan.FileOrderByName fileListParam.OrderBy = aliyunpan.FileOrderByName
fileListParam.OrderDirection = aliyunpan.FileOrderDirectionAsc fileListParam.OrderDirection = aliyunpan.FileOrderDirectionAsc
if targetPathInfo.IsFolder() { if targetPathInfo.IsFolder() {
fileResult, err := activeUser.PanClient().FileListGetAll(fileListParam, 500) fileResult, err := activeUser.PanClient().WebapiPanClient().FileListGetAll(fileListParam, 500)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return return
@@ -214,9 +214,9 @@ func getTree(driveId, pathStr string, depth int, statistic *treeStatistic, setti
// RunTree 列出树形图 // RunTree 列出树形图
func RunTree(driveId, pathStr string, showFullPath, showFileSize bool, minSize, maxSize int64) { func RunTree(driveId, pathStr string, showFullPath, showFileSize bool, minSize, maxSize int64) {
activeUser := config.Config.ActiveUser() activeUser := config.Config.ActiveUser()
activeUser.PanClient().ClearCache() activeUser.PanClient().WebapiPanClient().ClearCache()
activeUser.PanClient().EnableCache() activeUser.PanClient().WebapiPanClient().EnableCache()
defer activeUser.PanClient().DisableCache() defer activeUser.PanClient().WebapiPanClient().DisableCache()
pathStr = activeUser.PathJoin(driveId, pathStr) pathStr = activeUser.PathJoin(driveId, pathStr)
statistic := &treeStatistic{ statistic := &treeStatistic{
CountOfDir: 0, CountOfDir: 0,
+12 -12
View File
@@ -273,9 +273,9 @@ func CmdRapidUpload() cli.Command {
// RunUpload 执行文件上传 // RunUpload 执行文件上传
func RunUpload(localPaths []string, savePath string, opt *UploadOptions) { func RunUpload(localPaths []string, savePath string, opt *UploadOptions) {
activeUser := GetActiveUser() activeUser := GetActiveUser()
activeUser.PanClient().EnableCache() activeUser.PanClient().WebapiPanClient().EnableCache()
activeUser.PanClient().ClearCache() activeUser.PanClient().WebapiPanClient().ClearCache()
defer activeUser.PanClient().DisableCache() defer activeUser.PanClient().WebapiPanClient().DisableCache()
// pan token expired checker // pan token expired checker
continueFlag := int32(0) continueFlag := int32(0)
atomic.StoreInt32(&continueFlag, 0) atomic.StoreInt32(&continueFlag, 0)
@@ -316,13 +316,13 @@ func RunUpload(localPaths []string, savePath string, opt *UploadOptions) {
// 超时时间 // 超时时间
if opt.MaxTimeoutSec > 0 { if opt.MaxTimeoutSec > 0 {
activeUser.PanClient().SetTimeout(time.Duration(opt.MaxTimeoutSec) * time.Second) activeUser.PanClient().WebapiPanClient().SetTimeout(time.Duration(opt.MaxTimeoutSec) * time.Second)
} }
fmt.Printf("\n[0] 当前文件上传最大并发量为: %d, 上传分片大小为: %s\n", opt.AllParallel, converter.ConvertFileSize(opt.BlockSize, 2)) fmt.Printf("\n[0] 当前文件上传最大并发量为: %d, 上传分片大小为: %s\n", opt.AllParallel, converter.ConvertFileSize(opt.BlockSize, 2))
savePath = activeUser.PathJoin(opt.DriveId, savePath) savePath = activeUser.PathJoin(opt.DriveId, savePath)
_, err1 := activeUser.PanClient().FileInfoByPath(opt.DriveId, savePath) _, err1 := activeUser.PanClient().WebapiPanClient().FileInfoByPath(opt.DriveId, savePath)
if err1 != nil { if err1 != nil {
fmt.Printf("警告: 上传文件, 获取云盘路径 %s 错误, %s\n", savePath, err1) fmt.Printf("警告: 上传文件, 获取云盘路径 %s 错误, %s\n", savePath, err1)
} }
@@ -441,7 +441,7 @@ func RunUpload(localPaths []string, savePath string, opt *UploadOptions) {
LocalFileChecksum: localfile.NewLocalSymlinkFileEntity(file), LocalFileChecksum: localfile.NewLocalSymlinkFileEntity(file),
SavePath: subSavePath, SavePath: subSavePath,
DriveId: opt.DriveId, DriveId: opt.DriveId,
PanClient: activeUser.PanClient(), PanClient: activeUser.PanClient().WebapiPanClient(),
UploadingDatabase: uploadDatabase, UploadingDatabase: uploadDatabase,
FolderCreateMutex: folderCreateMutex, FolderCreateMutex: folderCreateMutex,
Parallel: opt.Parallel, Parallel: opt.Parallel,
@@ -463,11 +463,11 @@ func RunUpload(localPaths []string, savePath string, opt *UploadOptions) {
if saveFilePath != "/" { if saveFilePath != "/" {
folderCreateMutex.Lock() folderCreateMutex.Lock()
fmt.Printf("正在检测和创建云盘文件夹: %s\n", saveFilePath) fmt.Printf("正在检测和创建云盘文件夹: %s\n", saveFilePath)
_, apierr1 := activeUser.PanClient().FileInfoByPath(opt.DriveId, saveFilePath) _, apierr1 := activeUser.PanClient().WebapiPanClient().FileInfoByPath(opt.DriveId, saveFilePath)
time.Sleep(1 * time.Second) time.Sleep(1 * time.Second)
if apierr1 != nil && apierr1.Code == apierror.ApiCodeFileNotFoundCode { if apierr1 != nil && apierr1.Code == apierror.ApiCodeFileNotFoundCode {
logger.Verbosef("%s 创建云盘文件夹: %s\n", utils.NowTimeStr(), saveFilePath) logger.Verbosef("%s 创建云盘文件夹: %s\n", utils.NowTimeStr(), saveFilePath)
rs, apierr := activeUser.PanClient().Mkdir(opt.DriveId, "root", saveFilePath) rs, apierr := activeUser.PanClient().WebapiPanClient().Mkdir(opt.DriveId, "root", saveFilePath)
if apierr != nil || rs.FileId == "" { if apierr != nil || rs.FileId == "" {
fmt.Printf("创建云盘文件夹失败: %s\n", saveFilePath) fmt.Printf("创建云盘文件夹失败: %s\n", saveFilePath)
} }
@@ -565,7 +565,7 @@ func doRapidUpload(driveId string, isOverwrite bool, item *RapidUploadItem) erro
panDir, panFileName := path.Split(item.FilePath) panDir, panFileName := path.Split(item.FilePath)
saveFilePath = item.FilePath saveFilePath = item.FilePath
if panDir != "/" { if panDir != "/" {
rs, apierr = panClient.MkdirRecursive(driveId, "", "", 0, strings.Split(path.Clean(panDir), "/")) rs, apierr = panClient.WebapiPanClient().MkdirRecursive(driveId, "", "", 0, strings.Split(path.Clean(panDir), "/"))
if apierr != nil || rs.FileId == "" { if apierr != nil || rs.FileId == "" {
return fmt.Errorf("创建云盘文件夹失败") return fmt.Errorf("创建云盘文件夹失败")
} }
@@ -578,13 +578,13 @@ func doRapidUpload(driveId string, isOverwrite bool, item *RapidUploadItem) erro
if isOverwrite { if isOverwrite {
// 标记覆盖旧同名文件 // 标记覆盖旧同名文件
// 检查同名文件是否存在 // 检查同名文件是否存在
efi, apierr := panClient.FileInfoByPath(driveId, saveFilePath) efi, apierr := panClient.WebapiPanClient().FileInfoByPath(driveId, saveFilePath)
if apierr != nil && apierr.Code != apierror.ApiCodeFileNotFoundCode { if apierr != nil && apierr.Code != apierror.ApiCodeFileNotFoundCode {
return fmt.Errorf("检测同名文件失败,请稍后重试") return fmt.Errorf("检测同名文件失败,请稍后重试")
} }
if efi != nil && efi.FileId != "" { if efi != nil && efi.FileId != "" {
// existed, delete it // existed, delete it
fileDeleteResult, err1 := panClient.FileDelete([]*aliyunpan.FileBatchActionParam{{DriveId: efi.DriveId, FileId: efi.FileId}}) fileDeleteResult, err1 := panClient.WebapiPanClient().FileDelete([]*aliyunpan.FileBatchActionParam{{DriveId: efi.DriveId, FileId: efi.FileId}})
if err1 != nil || len(fileDeleteResult) == 0 { if err1 != nil || len(fileDeleteResult) == 0 {
return fmt.Errorf("无法删除文件,请稍后重试") return fmt.Errorf("无法删除文件,请稍后重试")
} }
@@ -604,7 +604,7 @@ func doRapidUpload(driveId string, isOverwrite bool, item *RapidUploadItem) erro
ContentHash: item.FileSha1, ContentHash: item.FileSha1,
ParentFileId: rs.FileId, ParentFileId: rs.FileId,
} }
uploadOpEntity, apierr := panClient.CreateUploadFile(appCreateUploadFileParam) uploadOpEntity, apierr := panClient.WebapiPanClient().CreateUploadFile(appCreateUploadFileParam)
if apierr != nil { if apierr != nil {
return fmt.Errorf("创建秒传任务失败:" + apierr.Error()) return fmt.Errorf("创建秒传任务失败:" + apierr.Error())
} }
+2 -2
View File
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // http://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
@@ -137,5 +137,5 @@ func CmdWho() cli.Command {
} }
func RunGetUserInfo() (userInfo *aliyunpan.UserInfo, error error) { func RunGetUserInfo() (userInfo *aliyunpan.UserInfo, error error) {
return GetActivePanClient().GetUserInfo() return GetActivePanClient().WebapiPanClient().GetUserInfo()
} }
+46 -110
View File
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // http://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
@@ -16,8 +16,6 @@ package command
import ( import (
"fmt" "fmt"
"github.com/tickstep/aliyunpan-api/aliyunpan" "github.com/tickstep/aliyunpan-api/aliyunpan"
"github.com/tickstep/aliyunpan-api/aliyunpan/apierror"
"github.com/tickstep/aliyunpan/cmder/cmdliner"
"github.com/tickstep/aliyunpan/internal/config" "github.com/tickstep/aliyunpan/internal/config"
"github.com/tickstep/aliyunpan/internal/functions/panlogin" "github.com/tickstep/aliyunpan/internal/functions/panlogin"
"github.com/tickstep/aliyunpan/internal/plugins" "github.com/tickstep/aliyunpan/internal/plugins"
@@ -60,7 +58,7 @@ var (
// RunTestShellPattern 执行测试通配符 // RunTestShellPattern 执行测试通配符
func RunTestShellPattern(driveId string, pattern string) { func RunTestShellPattern(driveId string, pattern string) {
acUser := GetActiveUser() acUser := GetActiveUser()
files, err := acUser.PanClient().MatchPathByShellPattern(driveId, GetActiveUser().PathJoin(driveId, pattern)) files, err := acUser.PanClient().WebapiPanClient().MatchPathByShellPattern(driveId, GetActiveUser().PathJoin(driveId, pattern))
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return return
@@ -75,7 +73,7 @@ func RunTestShellPattern(driveId string, pattern string) {
func matchPathByShellPattern(driveId string, patterns ...string) (files []*aliyunpan.FileEntity, e error) { func matchPathByShellPattern(driveId string, patterns ...string) (files []*aliyunpan.FileEntity, e error) {
acUser := GetActiveUser() acUser := GetActiveUser()
for k := range patterns { for k := range patterns {
ps, err := acUser.PanClient().MatchPathByShellPattern(driveId, acUser.PathJoin(driveId, patterns[k])) ps, err := acUser.PanClient().WebapiPanClient().MatchPathByShellPattern(driveId, acUser.PathJoin(driveId, patterns[k]))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -128,7 +126,21 @@ func UnescapeStr(s string) string {
return r return r
} }
// RefreshTokenInNeed 刷新refresh token func NewWebLoginToken(accessToken string, expired int64) aliyunpan.WebLoginToken {
webapiToken := &config.PanClientToken{
AccessToken: accessToken,
Expired: expired,
}
return aliyunpan.WebLoginToken{
AccessTokenType: "Bearer",
AccessToken: webapiToken.AccessToken,
RefreshToken: "",
ExpiresIn: 7200,
ExpireTime: webapiToken.GetExpiredTimeCstStr(),
}
}
// RefreshTokenInNeed 刷新webapi access token
func RefreshTokenInNeed(activeUser *config.PanUser, deviceName string) bool { func RefreshTokenInNeed(activeUser *config.PanUser, deviceName string) bool {
if activeUser == nil { if activeUser == nil {
return false return false
@@ -136,11 +148,11 @@ func RefreshTokenInNeed(activeUser *config.PanUser, deviceName string) bool {
// refresh expired token // refresh expired token
if activeUser.PanClient() != nil { if activeUser.PanClient() != nil {
if len(activeUser.WebToken.RefreshToken) > 0 { if len(activeUser.WebapiToken.AccessToken) > 0 {
cz := time.FixedZone("CST", 8*3600) // 东8区 cz := time.FixedZone("CST", 8*3600) // 东8区
expiredTime, _ := time.ParseInLocation("2006-01-02 15:04:05", activeUser.WebToken.ExpireTime, cz) expiredTime := time.Unix(activeUser.WebapiToken.Expired, 0).In(cz)
now := time.Now() now := time.Now()
if (expiredTime.Unix() - now.Unix()) <= (20 * 60) { // 20min if (expiredTime.Unix() - now.Unix()) <= (5 * 60) { // 有效期小于5min就刷新
pluginManger := plugins.NewPluginManager(config.GetPluginDir()) pluginManger := plugins.NewPluginManager(config.GetPluginDir())
plugin, _ := pluginManger.GetPlugin() plugin, _ := pluginManger.GetPlugin()
params := &plugins.UserTokenRefreshFinishParams{ params := &plugins.UserTokenRefreshFinishParams{
@@ -152,15 +164,23 @@ func RefreshTokenInNeed(activeUser *config.PanUser, deviceName string) bool {
} }
// need update refresh token // need update refresh token
logger.Verboseln("access token expired, get new from refresh token") logger.Verboseln("access token expired, get new from server")
if wt, er := aliyunpan.GetAccessTokenFromRefreshToken(activeUser.RefreshToken); er == nil { loginHelper := panlogin.NewLoginHelper(config.DefaultTokenServiceWebHost)
wt, e := loginHelper.GetWebapiNewToken(activeUser.TicketId, activeUser.UserId)
if e != nil {
logger.Verboseln("get web token from server error: ", e)
}
if wt != nil {
params.Result = "success" params.Result = "success"
params.OldToken = activeUser.RefreshToken params.OldToken = activeUser.WebapiToken.AccessToken
params.NewToken = wt.RefreshToken params.NewToken = wt.AccessToken
activeUser.RefreshToken = wt.RefreshToken userWebToken := NewWebLoginToken(wt.AccessToken, wt.Expired)
activeUser.WebToken = *wt activeUser.WebapiToken = &config.PanClientToken{
activeUser.PanClient().UpdateToken(*wt) AccessToken: wt.AccessToken,
Expired: wt.Expired,
}
activeUser.PanClient().WebapiPanClient().UpdateToken(userWebToken)
logger.Verboseln("get new access token success") logger.Verboseln("get new access token success")
// plugin callback // plugin callback
@@ -169,7 +189,7 @@ func RefreshTokenInNeed(activeUser *config.PanUser, deviceName string) bool {
} }
// create new signature // create new signature
_, e := activeUser.PanClient().CreateSession(nil) _, e := activeUser.PanClient().WebapiPanClient().CreateSession(nil)
if e != nil { if e != nil {
logger.Verboseln("call CreateSession error in RefreshTokenInNeed: " + e.Error()) logger.Verboseln("call CreateSession error in RefreshTokenInNeed: " + e.Error())
} }
@@ -179,8 +199,8 @@ func RefreshTokenInNeed(activeUser *config.PanUser, deviceName string) bool {
// if token has expired, callback plugin api for notify // if token has expired, callback plugin api for notify
if now.Unix() >= expiredTime.Unix() { if now.Unix() >= expiredTime.Unix() {
params.Result = "fail" params.Result = "fail"
params.Message = er.Error() params.Message = e.Error()
params.OldToken = activeUser.RefreshToken params.OldToken = activeUser.WebapiToken.AccessToken
if er1 := plugin.UserTokenRefreshFinishCallback(plugins.GetContext(activeUser), params); er1 != nil { if er1 := plugin.UserTokenRefreshFinishCallback(plugins.GetContext(activeUser), params); er1 != nil {
logger.Verbosef("UserTokenRefreshFinishCallback error: " + er1.Error()) logger.Verbosef("UserTokenRefreshFinishCallback error: " + er1.Error())
} }
@@ -205,110 +225,26 @@ func isMatchWildcardPattern(name string) bool {
return strings.ContainsAny(name, "*") || strings.ContainsAny(name, "?") || strings.ContainsAny(name, "[") return strings.ContainsAny(name, "*") || strings.ContainsAny(name, "?") || strings.ContainsAny(name, "[")
} }
// DoLoginHelper 登录助手,使用token进行登录
func DoLoginHelper(refreshToken string) (refreshTokenStr string, webToken aliyunpan.WebLoginToken, error error) {
line := cmdliner.NewLiner()
defer line.Close()
if refreshToken == "" {
refreshToken, error = line.State.Prompt("请输入RefreshToken, 回车键提交 > ")
if error != nil {
return
}
}
// app login
atoken, apperr := aliyunpan.GetAccessTokenFromRefreshToken(refreshToken)
if apperr != nil {
if apperr.Code == apierror.ApiCodeTokenExpiredCode || apperr.Code == apierror.ApiCodeRefreshTokenExpiredCode {
fmt.Println("Token过期,需要重新登录")
} else {
fmt.Println("Token登录失败:", apperr)
}
return "", webToken, fmt.Errorf("登录失败")
}
refreshTokenStr = refreshToken
return refreshTokenStr, *atoken, nil
}
// TryLogin 尝试登录,基础应用支持的各类登录方式进行尝试成功登录 // TryLogin 尝试登录,基础应用支持的各类登录方式进行尝试成功登录
func TryLogin() *config.PanUser { func TryLogin() *config.PanUser {
// 获取当前插件
pluginManger := plugins.NewPluginManager(config.GetPluginDir())
plugin, _ := pluginManger.GetPlugin()
params := &plugins.UserTokenRefreshFinishParams{
Result: "success",
Message: "",
OldToken: "",
NewToken: "",
UpdatedAt: utils.NowTimeStr(),
}
// can do automatically login? // can do automatically login?
for _, u := range config.Config.UserList { for _, u := range config.Config.UserList {
if u.UserId == config.Config.ActiveUID { if u.UserId == config.Config.ActiveUID {
// login // login
_, webToken, err := DoLoginHelper(u.RefreshToken) cloudUser, err := config.SetupUserByCookie(u.OpenapiToken, u.WebapiToken,
if err != nil { u.TicketId, u.UserId,
logger.Verboseln("automatically login use saved refresh token error ", err) config.Config.DeviceId, config.Config.DeviceName,
if u.TokenId != "" { config.Config.ClientId, config.Config.ClientSecret)
logger.Verboseln("try to login use tokenId") if cloudUser == nil {
h := panlogin.NewLoginHelper(config.DefaultTokenServiceWebHost) fmt.Println("尝试登录失败: ", err)
r, e := h.GetRefreshToken(u.TokenId) return nil
if e != nil {
logger.Verboseln("try to login use tokenId error", e)
// login fail plugin callback
params.Result = "fail"
params.OldToken = u.RefreshToken
params.NewToken = ""
if er := plugin.UserTokenRefreshFinishCallback(plugins.GetContext(u), params); er != nil {
logger.Verbosef("UserTokenRefreshFinishCallback error: " + er.Error())
}
break
}
refreshToken, e := h.ParseSecureRefreshToken("", r.SecureRefreshToken)
if e != nil {
logger.Verboseln("try to parse refresh token error", e)
break
}
_, webToken, err = DoLoginHelper(refreshToken)
if err != nil {
logger.Verboseln("try to use refresh token from tokenId error", e)
break
}
fmt.Println("Token重新自动登录成功")
// save new refresh token
u.RefreshToken = refreshToken
} else {
// login fail plugin callback
params.Result = "fail"
params.OldToken = u.RefreshToken
params.NewToken = ""
if er := plugin.UserTokenRefreshFinishCallback(plugins.GetContext(u), params); er != nil {
logger.Verbosef("UserTokenRefreshFinishCallback error: " + er.Error())
}
}
break
} }
// plugin param
params.Result = "success"
params.OldToken = u.RefreshToken
params.NewToken = webToken.RefreshToken
// success login, save new token and access token
u.RefreshToken = webToken.RefreshToken
u.WebToken = webToken
// save // save
SaveConfigFunc(nil) SaveConfigFunc(nil)
// reload // reload
ReloadConfigFunc(nil) ReloadConfigFunc(nil)
// do plugin callback
if er := plugin.UserTokenRefreshFinishCallback(plugins.GetContext(u), params); er != nil {
logger.Verbosef("UserTokenRefreshFinishCallback error: " + er.Error())
}
return config.Config.ActiveUser() return config.Config.ActiveUser()
} }
} }
+2 -2
View File
@@ -106,7 +106,7 @@ func RunXCopy(srcDriveId, dstDriveId string, paths ...string) {
copyFileParamList = append(copyFileParamList, mfi.FileId) copyFileParamList = append(copyFileParamList, mfi.FileId)
cacheCleanPaths = append(cacheCleanPaths, path.Dir(mfi.Path)) cacheCleanPaths = append(cacheCleanPaths, path.Dir(mfi.Path))
} }
fccr, er := activeUser.PanClient().FileCrossDriveCopy(&aliyunpan.FileCrossCopyParam{ fccr, er := activeUser.PanClient().WebapiPanClient().FileCrossDriveCopy(&aliyunpan.FileCrossCopyParam{
FromDriveId: srcDriveId, FromDriveId: srcDriveId,
FromFileIds: copyFileParamList, FromFileIds: copyFileParamList,
ToDriveId: dstDriveId, ToDriveId: dstDriveId,
@@ -151,7 +151,7 @@ func getCrossCopyFileInfo(srcDriveId, dstDriveId string, paths ...string) (opFil
// the last one is the target file path // the last one is the target file path
targetFilePath := path.Clean(paths[len(paths)-1]) targetFilePath := path.Clean(paths[len(paths)-1])
absolutePath := activeUser.PathJoin(dstDriveId, targetFilePath) absolutePath := activeUser.PathJoin(dstDriveId, targetFilePath)
targetFile, err := activeUser.PanClient().FileInfoByPath(dstDriveId, absolutePath) targetFile, err := activeUser.PanClient().WebapiPanClient().FileInfoByPath(dstDriveId, absolutePath)
if err != nil || !targetFile.IsFolder() { if err != nil || !targetFile.IsFolder() {
return nil, nil, nil, fmt.Errorf("指定目标文件夹不存在") return nil, nil, nil, fmt.Errorf("指定目标文件夹不存在")
} }
+2 -2
View File
@@ -30,7 +30,7 @@ func (pu *PanUser) DeleteOneCache(dirPath string) {
func (pu *PanUser) CacheFilesDirectoriesList(pathStr string) (fdl aliyunpan.FileList, apiError *apierror.ApiError) { func (pu *PanUser) CacheFilesDirectoriesList(pathStr string) (fdl aliyunpan.FileList, apiError *apierror.ApiError) {
data := pu.cacheOpMap.CacheOperation(pu.ActiveDriveId, pathStr+"_OrderByName", func() expires.DataExpires { data := pu.cacheOpMap.CacheOperation(pu.ActiveDriveId, pathStr+"_OrderByName", func() expires.DataExpires {
var fi *aliyunpan.FileEntity var fi *aliyunpan.FileEntity
fi, apiError = pu.panClient.FileInfoByPath(pu.ActiveDriveId, pathStr) fi, apiError = pu.panClient.WebapiPanClient().FileInfoByPath(pu.ActiveDriveId, pathStr)
if apiError != nil { if apiError != nil {
return nil return nil
} }
@@ -38,7 +38,7 @@ func (pu *PanUser) CacheFilesDirectoriesList(pathStr string) (fdl aliyunpan.File
DriveId: pu.ActiveDriveId, DriveId: pu.ActiveDriveId,
ParentFileId: fi.FileId, ParentFileId: fi.FileId,
} }
fdl, apiError = pu.panClient.FileListGetAll(fileListParam, 100) fdl, apiError = pu.panClient.WebapiPanClient().FileListGetAll(fileListParam, 100)
if apiError != nil { if apiError != nil {
return nil return nil
} }
+31
View File
@@ -0,0 +1,31 @@
package config
import (
"github.com/tickstep/aliyunpan-api/aliyunpan"
"github.com/tickstep/aliyunpan-api/aliyunpan_open"
)
type (
// PanClient 云盘客户端
PanClient struct {
// 网页WEB接口客户端
webapiPanClient *aliyunpan.PanClient
// 阿里openapi接口客户端
openapiPanClient *aliyunpan_open.OpenPanClient
}
)
func NewPanClient(webClient *aliyunpan.PanClient, openClient *aliyunpan_open.OpenPanClient) *PanClient {
return &PanClient{
webapiPanClient: webClient,
openapiPanClient: openClient,
}
}
func (p *PanClient) WebapiPanClient() *aliyunpan.PanClient {
return p.webapiPanClient
}
func (p *PanClient) OpenapiPanClient() *aliyunpan_open.OpenPanClient {
return p.openapiPanClient
}
+21 -12
View File
@@ -61,6 +61,9 @@ const (
// DefaultDeviceName 默认客户端名称 // DefaultDeviceName 默认客户端名称
DefaultDeviceName = "Chrome浏览器" DefaultDeviceName = "Chrome浏览器"
// DefaultClientId 默认的clientId
DefaultClientId = "cf9f70e8fc61430f8ec5ab5cadf31375"
) )
var ( var (
@@ -69,11 +72,6 @@ var (
// Config 配置信息, 由外部调用 // Config 配置信息, 由外部调用
Config = NewConfig(configFilePath) Config = NewConfig(configFilePath)
AppVersion string
// IsAppInCliMode 是否在交互模式
IsAppInCliMode = false
) )
type UpdateCheckInfo struct { type UpdateCheckInfo struct {
@@ -110,6 +108,10 @@ type PanConfig struct {
DeviceId string `json:"deviceId"` // 客户端ID,用于标识登录客户端,阿里单个账号最多允许10个客户端同时登录 DeviceId string `json:"deviceId"` // 客户端ID,用于标识登录客户端,阿里单个账号最多允许10个客户端同时登录
DeviceName string `json:"deviceName"` // 客户端名称,默认为:Chrome浏览器 DeviceName string `json:"deviceName"` // 客户端名称,默认为:Chrome浏览器
// Openapi客户端信息
ClientId string `json:"clientId"`
ClientSecret string `json:"clientSecret"`
configFilePath string configFilePath string
configFile *os.File configFile *os.File
fileMu sync.Mutex fileMu sync.Mutex
@@ -270,6 +272,9 @@ func (c *PanConfig) loadConfigFromFile() (err error) {
if c.DeviceName == "" { if c.DeviceName == "" {
c.DeviceName = DefaultDeviceName c.DeviceName = DefaultDeviceName
} }
if c.ClientId == "" {
c.ClientId = DefaultClientId
}
return nil return nil
} }
@@ -294,6 +299,7 @@ func (c *PanConfig) initDefaultConfig() {
c.VideoFileExtensions = DefaultVideoFileExtensions c.VideoFileExtensions = DefaultVideoFileExtensions
c.DeviceId = RandomDeviceId() // 生成默认客户端ID c.DeviceId = RandomDeviceId() // 生成默认客户端ID
c.DeviceName = DefaultDeviceName c.DeviceName = DefaultDeviceName
c.ClientId = DefaultClientId
c.FileRecordConfig = "1" // 默认开启 c.FileRecordConfig = "1" // 默认开启
c.PreferIPType = "ipv4" // 默认优先IPv4 c.PreferIPType = "ipv4" // 默认优先IPv4
} }
@@ -390,7 +396,10 @@ func (c *PanConfig) ActiveUser() *PanUser {
if u.UserId == c.ActiveUID { if u.UserId == c.ActiveUID {
if u.PanClient() == nil { if u.PanClient() == nil {
// restore client // restore client
user, err := SetupUserByCookie(&u.WebToken, c.DeviceId, c.DeviceName) user, err := SetupUserByCookie(u.OpenapiToken, u.WebapiToken,
u.TicketId, u.UserId,
c.DeviceId, c.DeviceName,
c.ClientId, c.ClientSecret)
if err != nil { if err != nil {
logger.Verboseln("setup user error") logger.Verboseln("setup user error")
return nil return nil
@@ -401,7 +410,7 @@ func (c *PanConfig) ActiveUser() *PanUser {
u.DriveList = user.DriveList u.DriveList = user.DriveList
// check workdir valid or not // check workdir valid or not
if user.IsFileDriveActive() { if user.IsFileDriveActive() {
fe, err1 := u.PanClient().FileInfoByPath(u.ActiveDriveId, u.Workdir) fe, err1 := u.PanClient().WebapiPanClient().FileInfoByPath(u.ActiveDriveId, u.Workdir)
if err1 != nil { if err1 != nil {
// default to root // default to root
u.Workdir = "/" u.Workdir = "/"
@@ -410,7 +419,7 @@ func (c *PanConfig) ActiveUser() *PanUser {
u.WorkdirFileEntity = *fe u.WorkdirFileEntity = *fe
} }
} else if user.IsResourceDriveActive() { } else if user.IsResourceDriveActive() {
fe, err1 := u.PanClient().FileInfoByPath(u.ActiveDriveId, u.ResourceWorkdir) fe, err1 := u.PanClient().WebapiPanClient().FileInfoByPath(u.ActiveDriveId, u.ResourceWorkdir)
if err1 != nil { if err1 != nil {
// default to root // default to root
u.ResourceWorkdir = "/" u.ResourceWorkdir = "/"
@@ -419,7 +428,7 @@ func (c *PanConfig) ActiveUser() *PanUser {
u.ResourceWorkdirFileEntity = *fe u.ResourceWorkdirFileEntity = *fe
} }
} else if user.IsAlbumDriveActive() { } else if user.IsAlbumDriveActive() {
fe, err1 := u.PanClient().FileInfoByPath(u.ActiveDriveId, u.AlbumWorkdir) fe, err1 := u.PanClient().WebapiPanClient().FileInfoByPath(u.ActiveDriveId, u.AlbumWorkdir)
if err1 != nil { if err1 != nil {
// default to root // default to root
u.AlbumWorkdir = "/" u.AlbumWorkdir = "/"
@@ -444,9 +453,9 @@ func (c *PanConfig) SetActiveUser(user *PanUser) *PanUser {
if u.UserId == user.UserId { if u.UserId == user.UserId {
// update user info // update user info
u.Nickname = user.Nickname u.Nickname = user.Nickname
u.WebToken = user.WebToken u.WebapiToken = user.WebapiToken
u.RefreshToken = user.RefreshToken u.OpenapiToken = user.OpenapiToken
u.TokenId = user.TokenId u.TicketId = user.TicketId
needToInsert = false needToInsert = false
break break
} }
+157 -66
View File
@@ -17,10 +17,14 @@ import (
"fmt" "fmt"
"github.com/tickstep/aliyunpan-api/aliyunpan" "github.com/tickstep/aliyunpan-api/aliyunpan"
"github.com/tickstep/aliyunpan-api/aliyunpan/apierror" "github.com/tickstep/aliyunpan-api/aliyunpan/apierror"
"github.com/tickstep/aliyunpan-api/aliyunpan_open"
"github.com/tickstep/aliyunpan-api/aliyunpan_open/openapi"
"github.com/tickstep/aliyunpan/internal/functions/panlogin"
"github.com/tickstep/library-go/expires/cachemap" "github.com/tickstep/library-go/expires/cachemap"
"github.com/tickstep/library-go/logger" "github.com/tickstep/library-go/logger"
"path" "path"
"path/filepath" "path/filepath"
"time"
) )
type DriveInfo struct { type DriveInfo struct {
@@ -57,12 +61,28 @@ func (d DriveInfoList) GetResourceDriveId() string {
return "" return ""
} }
// PanClientToken 授权Token
type PanClientToken struct {
// AccessToken AccessToken
AccessToken string `json:"accessToken"`
// Expired 过期时间戳,单位秒
Expired int64 `json:"expired"`
}
// GetExpiredTimeCstStr 获取东八区时间字符串
func (t *PanClientToken) GetExpiredTimeCstStr() string {
cz := time.FixedZone("CST", 8*3600) // 东8区
tm := time.Unix(t.Expired, 0).In(cz)
return tm.Format("2006-01-02 15:04:05")
}
type PanUser struct { type PanUser struct {
// 用户信息
UserId string `json:"userId"` UserId string `json:"userId"`
Nickname string `json:"nickname"` Nickname string `json:"nickname"`
AccountName string `json:"accountName"` AccountName string `json:"accountName"`
// 文件/备份盘 // 文件(备份盘)
Workdir string `json:"workdir"` Workdir string `json:"workdir"`
WorkdirFileEntity aliyunpan.FileEntity `json:"workdirFileEntity"` WorkdirFileEntity aliyunpan.FileEntity `json:"workdirFileEntity"`
@@ -74,89 +94,115 @@ type PanUser struct {
AlbumWorkdir string `json:"albumWorkdir"` AlbumWorkdir string `json:"albumWorkdir"`
AlbumWorkdirFileEntity aliyunpan.FileEntity `json:"albumWorkdirFileEntity"` AlbumWorkdirFileEntity aliyunpan.FileEntity `json:"albumWorkdirFileEntity"`
// 用户网盘信息
ActiveDriveId string `json:"activeDriveId"` ActiveDriveId string `json:"activeDriveId"`
DriveList DriveInfoList `json:"driveList"` DriveList DriveInfoList `json:"driveList"`
RefreshToken string `json:"refreshToken"` // 授权Token信息
WebToken aliyunpan.WebLoginToken `json:"webToken"` TicketId string `json:"ticketId"`
TokenId string `json:"tokenId"` WebapiToken *PanClientToken `json:"webapiToken"`
OpenapiToken *PanClientToken `json:"openapiToken"`
panClient *aliyunpan.PanClient // API客户端
cacheOpMap cachemap.CacheOpMap //panClient *aliyunpan.PanClient `json:"-"`
panClient *PanClient `json:"-"`
cacheOpMap cachemap.CacheOpMap `json:"-"`
} }
type PanUserList []*PanUser type PanUserList []*PanUser
func SetupUserByCookie(webToken *aliyunpan.WebLoginToken, deviceId, deviceName string) (user *PanUser, err *apierror.ApiError) { func SetupUserByCookie(openapiToken, webapiToken *PanClientToken, ticketId, userId, deviceId, deviceName, clientId, clientSecret string) (user *PanUser, err *apierror.ApiError) {
tryRefreshWebToken := true tryRefreshWebToken := true
tryRefreshOpenToken := true
loginHelper := panlogin.NewLoginHelper(DefaultTokenServiceWebHost)
if webToken == nil { if openapiToken == nil {
return nil, apierror.NewFailedApiError("web token is empty") return nil, apierror.NewFailedApiError("openapi token is empty")
}
if webapiToken == nil {
return nil, apierror.NewFailedApiError("webapi token is empty")
} }
doLoginAct: doOpenLoginAct:
appConfig := aliyunpan.AppConfig{ // setup openapi client
AppId: "25dzX3vbYqktVxyX", openPanClient := aliyunpan_open.NewOpenPanClient(openapi.ApiConfig{
DeviceId: deviceId, TicketId: ticketId,
UserId: "", UserId: userId,
Nonce: 0, ClientId: clientId,
PublicKey: "", ClientSecret: clientSecret,
} }, openapi.ApiToken{
panClient := aliyunpan.NewPanClient(*webToken, aliyunpan.AppLoginToken{}, appConfig, aliyunpan.SessionConfig{ AccessToken: openapiToken.AccessToken,
DeviceName: deviceName, ExpiredAt: openapiToken.Expired,
ModelName: "Windows网页版", }, func(newToken openapi.ApiToken) error {
// TODO: save & refresh new token
return nil
}) })
u := &PanUser{ // open api token maybe expired
WebToken: *webToken, // check & refresh new one
panClient: panClient, openUserInfo, err := openPanClient.GetUserInfo()
Workdir: "/",
WorkdirFileEntity: *aliyunpan.NewFileEntityForRootDir(),
}
// web api token maybe expired
userInfo, err := panClient.GetUserInfo()
if err != nil { if err != nil {
if err.Code == apierror.ApiCodeTokenExpiredCode && tryRefreshWebToken { if err.Code == apierror.ApiCodeTokenExpiredCode && tryRefreshOpenToken {
tryRefreshWebToken = false tryRefreshOpenToken = false
webCookie, _ := aliyunpan.GetAccessTokenFromRefreshToken(webToken.RefreshToken) wt, e := loginHelper.GetOpenapiNewToken(ticketId, userId)
if webCookie != nil { if e != nil {
webToken = webCookie logger.Verboseln("get openapi token from server error: ", e)
goto doLoginAct return nil, apierror.NewFailedApiError("get new openapi token error, try login again")
}
if wt != nil {
openapiToken = &PanClientToken{
AccessToken: wt.AccessToken,
Expired: wt.Expired,
}
goto doOpenLoginAct
} }
} }
return nil, err return nil, err
} }
name := "Unknown"
if userInfo != nil {
if userInfo.Nickname != "" {
name = userInfo.Nickname
}
// update user doWebLoginAct:
u.UserId = userInfo.UserId // setup webapi client
u.Nickname = name appConfig := aliyunpan.AppConfig{
u.AccountName = userInfo.UserName AppId: "25dzX3vbYqktVxyX",
DeviceId: deviceId,
// default file drive UserId: userId,
if u.ActiveDriveId == "" { Nonce: 0,
u.ActiveDriveId = userInfo.FileDriveId PublicKey: "",
}
webPanClient := aliyunpan.NewPanClient(aliyunpan.WebLoginToken{
AccessTokenType: "Bearer",
AccessToken: webapiToken.AccessToken,
RefreshToken: "",
ExpiresIn: 7200,
ExpireTime: webapiToken.GetExpiredTimeCstStr(),
}, aliyunpan.AppLoginToken{}, appConfig, aliyunpan.SessionConfig{
DeviceName: deviceName,
ModelName: "Windows网页版",
})
// web api token maybe expired
// check & refresh new one
webUserInfo, err2 := webPanClient.GetUserInfo()
if err != nil {
if err2.Code == apierror.ApiCodeTokenExpiredCode && tryRefreshWebToken {
tryRefreshWebToken = false
wt, e := loginHelper.GetWebapiNewToken(ticketId, userId)
if e != nil {
logger.Verboseln("get web token from server error: ", e)
}
if wt != nil {
webapiToken = &PanClientToken{
AccessToken: wt.AccessToken,
Expired: wt.Expired,
}
goto doWebLoginAct
}
} }
return nil, err
// drive list
u.DriveList = DriveInfoList{
{DriveId: userInfo.FileDriveId, DriveTag: "File", DriveName: "备份盘"},
{DriveId: userInfo.ResourceDriveId, DriveTag: "Resource", DriveName: "资源库"},
{DriveId: userInfo.AlbumDriveId, DriveTag: "Album", DriveName: "相册"},
}
} else {
// error, maybe the token has expired
return nil, apierror.NewFailedApiError("cannot get user info, the token has expired")
} }
// create session // web create session
appConfig.UserId = u.UserId appConfig.UserId = webUserInfo.UserId
panClient.UpdateAppConfig(appConfig) webPanClient.UpdateAppConfig(appConfig)
r, e := panClient.CreateSession(nil) r, e := webPanClient.CreateSession(nil)
if e != nil { if e != nil {
logger.Verboseln("call CreateSession error in SetupUserByCookie: " + e.Error()) logger.Verboseln("call CreateSession error in SetupUserByCookie: " + e.Error())
} }
@@ -164,10 +210,56 @@ doLoginAct:
logger.Verboseln("上传签名秘钥失败,可能是你账号登录的设备已超最大数量") logger.Verboseln("上传签名秘钥失败,可能是你账号登录的设备已超最大数量")
} }
//
// setup PanUser
//
u := &PanUser{
WebapiToken: webapiToken,
OpenapiToken: openapiToken,
panClient: NewPanClient(webPanClient, openPanClient),
Workdir: "/",
WorkdirFileEntity: *aliyunpan.NewFileEntityForRootDir(),
}
// setup user info
name := "Unknown"
if openUserInfo != nil {
// fill userId for client
u.PanClient().OpenapiPanClient().UpdateUserId(openUserInfo.UserId)
u.PanClient().WebapiPanClient().UpdateUserId(openUserInfo.UserId)
// update user
if openUserInfo.Nickname != "" {
name = openUserInfo.Nickname
}
u.UserId = openUserInfo.UserId
u.Nickname = name
u.AccountName = openUserInfo.UserName
// default file drive
if u.ActiveDriveId == "" {
u.ActiveDriveId = openUserInfo.FileDriveId
}
// drive list
u.DriveList = DriveInfoList{
{DriveId: openUserInfo.FileDriveId, DriveTag: "File", DriveName: "备份盘"},
{DriveId: openUserInfo.ResourceDriveId, DriveTag: "Resource", DriveName: "资源库"},
}
if webUserInfo != nil {
u.AccountName = webUserInfo.UserName
u.DriveList = append(u.DriveList, &DriveInfo{DriveId: webUserInfo.AlbumDriveId, DriveTag: "Album", DriveName: "相册"})
}
} else {
// error, maybe the token has expired
return nil, apierror.NewFailedApiError("cannot get user info, the token has expired. please login again")
}
// return user
return u, nil return u, nil
} }
func (pu *PanUser) PanClient() *aliyunpan.PanClient { func (pu *PanUser) PanClient() *PanClient {
return pu.panClient return pu.panClient
} }
@@ -192,21 +284,20 @@ func (pu *PanUser) PathJoin(driveId, p string) string {
func (pu *PanUser) FreshWorkdirInfo() { func (pu *PanUser) FreshWorkdirInfo() {
if pu.IsFileDriveActive() { if pu.IsFileDriveActive() {
fe, err := pu.PanClient().FileInfoById(pu.ActiveDriveId, pu.WorkdirFileEntity.FileId) fe, err := pu.PanClient().WebapiPanClient().FileInfoById(pu.ActiveDriveId, pu.WorkdirFileEntity.FileId)
if err != nil { if err != nil {
logger.Verboseln("刷新工作目录信息失败") logger.Verboseln("刷新工作目录信息失败")
return return
} }
pu.WorkdirFileEntity = *fe pu.WorkdirFileEntity = *fe
} else if pu.IsAlbumDriveActive() { } else if pu.IsAlbumDriveActive() {
fe, err := pu.PanClient().FileInfoById(pu.ActiveDriveId, pu.AlbumWorkdirFileEntity.FileId) fe, err := pu.PanClient().WebapiPanClient().FileInfoById(pu.ActiveDriveId, pu.AlbumWorkdirFileEntity.FileId)
if err != nil { if err != nil {
logger.Verboseln("刷新工作目录信息失败") logger.Verboseln("刷新工作目录信息失败")
return return
} }
pu.AlbumWorkdirFileEntity = *fe pu.AlbumWorkdirFileEntity = *fe
} }
} }
// GetSavePath 根据提供的网盘文件路径 panpath, 返回本地储存路径, // GetSavePath 根据提供的网盘文件路径 panpath, 返回本地储存路径,
+136 -5
View File
@@ -4,7 +4,7 @@ import (
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/tickstep/aliyunpan/internal/config" "github.com/tickstep/aliyunpan/internal/global"
"github.com/tickstep/aliyunpan/internal/utils" "github.com/tickstep/aliyunpan/internal/utils"
"github.com/tickstep/library-go/crypto" "github.com/tickstep/library-go/crypto"
"github.com/tickstep/library-go/getip" "github.com/tickstep/library-go/getip"
@@ -40,6 +40,17 @@ type QRCodeLoginResult struct {
SecureRefreshToken string `json:"secureRefreshToken"` SecureRefreshToken string `json:"secureRefreshToken"`
} }
// LoginTokenResult Token结果
type LoginTokenResult struct {
AccessToken string `json:"accessToken"`
Expired int64 `json:"expired"`
}
type CommonTokenEntity struct {
Openapi *LoginTokenResult `json:"openapi"`
Webapi *LoginTokenResult `json:"webapi"`
}
func NewLoginHelper(webHost string) *LoginHelper { func NewLoginHelper(webHost string) *LoginHelper {
return &LoginHelper{ return &LoginHelper{
webHost: webHost, webHost: webHost,
@@ -57,13 +68,13 @@ func (h *LoginHelper) GetQRCodeLoginUrl(keyStr string) (*QRCodeUrlResult, error)
ipAddr = "127.0.0.1" ipAddr = "127.0.0.1"
} }
fmt.Fprintf(&fullUrl, "%s/auth/tickstep/aliyunpan/token/qrcode/create?ip=%s&os=%s&arch=%s&version=%s&key=%s", fmt.Fprintf(&fullUrl, "%s/auth/tickstep/aliyunpan/token/qrcode/create?ip=%s&os=%s&arch=%s&version=%s&key=%s",
h.webHost, ipAddr, runtime.GOOS, runtime.GOARCH, config.AppVersion, keyStr) h.webHost, ipAddr, runtime.GOOS, runtime.GOARCH, global.AppVersion, keyStr)
logger.Verboseln("do request url: " + fullUrl.String()) logger.Verboseln("do request url: " + fullUrl.String())
header := map[string]string{ header := map[string]string{
"accept": "application/json, text/plain, */*", "accept": "application/json, text/plain, */*",
"content-type": "application/json;charset=UTF-8", "content-type": "application/json;charset=UTF-8",
"user-agent": "aliyunpan/" + config.AppVersion, "user-agent": "aliyunpan/" + global.AppVersion,
} }
// request // request
client := requester.NewHTTPClient() client := requester.NewHTTPClient()
@@ -114,7 +125,7 @@ func (h *LoginHelper) GetQRCodeLoginResult(tokenId string) (*QRCodeLoginResult,
header := map[string]string{ header := map[string]string{
"accept": "application/json, text/plain, */*", "accept": "application/json, text/plain, */*",
"content-type": "application/json;charset=UTF-8", "content-type": "application/json;charset=UTF-8",
"user-agent": "aliyunpan/" + config.AppVersion, "user-agent": "aliyunpan/" + global.AppVersion,
} }
// request // request
client := requester.NewHTTPClient() client := requester.NewHTTPClient()
@@ -154,7 +165,7 @@ func (h *LoginHelper) GetRefreshToken(tokenId string) (*QRCodeLoginResult, error
header := map[string]string{ header := map[string]string{
"accept": "application/json, text/plain, */*", "accept": "application/json, text/plain, */*",
"content-type": "application/json;charset=UTF-8", "content-type": "application/json;charset=UTF-8",
"user-agent": "aliyunpan/" + config.AppVersion, "user-agent": "aliyunpan/" + global.AppVersion,
} }
// request // request
client := requester.NewHTTPClient() client := requester.NewHTTPClient()
@@ -220,3 +231,123 @@ func (h *LoginHelper) ParseSecureRefreshToken(keyStr, secureRefreshToken string)
} }
return refreshToken, nil return refreshToken, nil
} }
// GetWebapiNewToken 获取Webapi Token
func (h *LoginHelper) GetWebapiNewToken(ticketId, userId string) (*LoginTokenResult, error) {
fullUrl := strings.Builder{}
fmt.Fprintf(&fullUrl, "%s/auth/tickstep/aliyunpan/token/webapi/%s/refresh?userId=%s",
h.webHost, ticketId, userId)
logger.Verboseln("do request url: " + fullUrl.String())
header := map[string]string{
"accept": "application/json, text/plain, */*",
"content-type": "application/json;charset=UTF-8",
"user-agent": "aliyunpan/" + global.AppVersion,
}
// request
client := requester.NewHTTPClient()
client.SetTimeout(20 * time.Second)
client.SetKeepAlive(false)
body, err := client.Fetch("GET", fullUrl.String(), nil, header)
if err != nil {
logger.Verboseln("get web token result error ", err)
return nil, err
}
errResp := &LoginHttpResult{}
if err1 := json.Unmarshal(body, errResp); err1 != nil {
logger.Verboseln("parse result json error ", err1)
return nil, err1
}
if errResp.Code != 0 {
return nil, fmt.Errorf(errResp.Msg)
}
// parse result
r := &LoginHttpResult{}
r.Data = &LoginTokenResult{}
if err2 := json.Unmarshal(body, r); err2 != nil {
logger.Verboseln("parse web token result json error ", err2)
return nil, err2
}
return r.Data.(*LoginTokenResult), nil
}
// GetOpenapiNewToken 获取Openapi Token
func (h *LoginHelper) GetOpenapiNewToken(ticketId, userId string) (*LoginTokenResult, error) {
fullUrl := strings.Builder{}
fmt.Fprintf(&fullUrl, "%s/auth/tickstep/aliyunpan/token/openapi/%s/refresh?userId=%s",
h.webHost, ticketId, userId)
logger.Verboseln("do request url: " + fullUrl.String())
header := map[string]string{
"accept": "application/json, text/plain, */*",
"content-type": "application/json;charset=UTF-8",
"user-agent": "aliyunpan/" + global.AppVersion,
}
// request
client := requester.NewHTTPClient()
client.SetTimeout(20 * time.Second)
client.SetKeepAlive(false)
body, err := client.Fetch("GET", fullUrl.String(), nil, header)
if err != nil {
logger.Verboseln("get openapi token result error ", err)
return nil, err
}
errResp := &LoginHttpResult{}
if err1 := json.Unmarshal(body, errResp); err1 != nil {
logger.Verboseln("parse result json error ", err1)
return nil, err1
}
if errResp.Code != 0 {
return nil, fmt.Errorf(errResp.Msg)
}
// parse result
r := &LoginHttpResult{}
r.Data = &LoginTokenResult{}
if err2 := json.Unmarshal(body, r); err2 != nil {
logger.Verboseln("parse openapi token result json error ", err2)
return nil, err2
}
return r.Data.(*LoginTokenResult), nil
}
// GetLoginToken 获取登录后的Token
func (h *LoginHelper) GetLoginToken(ticketId string) (*CommonTokenEntity, error) {
fullUrl := strings.Builder{}
fmt.Fprintf(&fullUrl, "%s/auth/tickstep/aliyunpan/token/common/%s/login",
h.webHost, ticketId)
logger.Verboseln("do request url: " + fullUrl.String())
header := map[string]string{
"accept": "application/json, text/plain, */*",
"content-type": "application/json;charset=UTF-8",
"user-agent": "aliyunpan/" + global.AppVersion,
}
// request
client := requester.NewHTTPClient()
client.SetTimeout(20 * time.Second)
client.SetKeepAlive(false)
body, err := client.Fetch("GET", fullUrl.String(), nil, header)
if err != nil {
logger.Verboseln("get login token result error ", err)
return nil, err
}
errResp := &LoginHttpResult{}
if err1 := json.Unmarshal(body, errResp); err1 != nil {
logger.Verboseln("parse result json error ", err1)
return nil, err1
}
if errResp.Code != 0 {
return nil, fmt.Errorf(errResp.Msg)
}
// parse result
r := &LoginHttpResult{}
r.Data = &CommonTokenEntity{}
if err2 := json.Unmarshal(body, r); err2 != nil {
logger.Verboseln("parse login token result json error ", err2)
return nil, err2
}
return r.Data.(*CommonTokenEntity), nil
}
+9
View File
@@ -0,0 +1,9 @@
package global
var (
// AppVersion 应用版本
AppVersion string
// IsAppInCliMode 是否在交互模式
IsAppInCliMode = false
)
+3 -2
View File
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // http://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
@@ -21,6 +21,7 @@ import (
"github.com/tickstep/aliyunpan/cmder/cmdliner" "github.com/tickstep/aliyunpan/cmder/cmdliner"
"github.com/tickstep/aliyunpan/cmder/cmdutil" "github.com/tickstep/aliyunpan/cmder/cmdutil"
"github.com/tickstep/aliyunpan/internal/config" "github.com/tickstep/aliyunpan/internal/config"
"github.com/tickstep/aliyunpan/internal/global"
"github.com/tickstep/aliyunpan/internal/utils" "github.com/tickstep/aliyunpan/internal/utils"
"github.com/tickstep/aliyunpan/library/requester/transfer" "github.com/tickstep/aliyunpan/library/requester/transfer"
"github.com/tickstep/library-go/cachepool" "github.com/tickstep/library-go/cachepool"
@@ -66,7 +67,7 @@ func getReleaseFromTicstep(client *requester.HTTPClient, showPrompt bool) *Relea
ipAddr = "127.0.0.1" ipAddr = "127.0.0.1"
} }
fmt.Fprintf(&fullUrl, "http://api.tickstep.com/update/tickstep/aliyunpan/releases/latest?ip=%s&os=%s&arch=%s&version=%s", fmt.Fprintf(&fullUrl, "http://api.tickstep.com/update/tickstep/aliyunpan/releases/latest?ip=%s&os=%s&arch=%s&version=%s",
ipAddr, runtime.GOOS, runtime.GOARCH, config.AppVersion) ipAddr, runtime.GOOS, runtime.GOARCH, global.AppVersion)
resp, err := client.Req(http.MethodGet, fullUrl.String(), nil, nil) resp, err := client.Req(http.MethodGet, fullUrl.String(), nil, nil)
if resp != nil { if resp != nil {
defer resp.Body.Close() defer resp.Body.Close()
+3 -2
View File
@@ -3,6 +3,7 @@ package plugins
import ( import (
"fmt" "fmt"
"github.com/tickstep/aliyunpan/internal/config" "github.com/tickstep/aliyunpan/internal/config"
"github.com/tickstep/aliyunpan/internal/global"
"github.com/tickstep/library-go/logger" "github.com/tickstep/library-go/logger"
"io/ioutil" "io/ioutil"
"os" "os"
@@ -21,7 +22,7 @@ func GetContext(user *config.PanUser) *Context {
if user == nil { if user == nil {
return &Context{ return &Context{
AppName: "aliyunpan", AppName: "aliyunpan",
Version: config.AppVersion, Version: global.AppVersion,
UserId: "", UserId: "",
Nickname: "", Nickname: "",
FileDriveId: "", FileDriveId: "",
@@ -30,7 +31,7 @@ func GetContext(user *config.PanUser) *Context {
} }
return &Context{ return &Context{
AppName: "aliyunpan", AppName: "aliyunpan",
Version: config.AppVersion, Version: global.AppVersion,
UserId: user.UserId, UserId: user.UserId,
Nickname: user.Nickname, Nickname: user.Nickname,
FileDriveId: user.DriveList.GetFileDriveId(), FileDriveId: user.DriveList.GetFileDriveId(),
+6 -5
View File
@@ -15,6 +15,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/tickstep/aliyunpan/internal/global"
"io/ioutil" "io/ioutil"
"os" "os"
"os/exec" "os/exec"
@@ -61,7 +62,7 @@ var (
) )
func init() { func init() {
config.AppVersion = Version global.AppVersion = Version
cmdutil.ChWorkDir() cmdutil.ChWorkDir()
err := config.Config.Init() err := config.Config.Init()
@@ -147,7 +148,7 @@ func main() {
os.Setenv(config.EnvVerbose, c.String("verbose")) os.Setenv(config.EnvVerbose, c.String("verbose"))
isCli = true isCli = true
config.IsAppInCliMode = true global.IsAppInCliMode = true
logger.Verbosef("提示: 你已经开启VERBOSE调试日志\n\n") logger.Verbosef("提示: 你已经开启VERBOSE调试日志\n\n")
var ( var (
@@ -309,9 +310,9 @@ func main() {
// check update // check update
command.ReloadConfigFunc(c) command.ReloadConfigFunc(c)
if config.Config.UpdateCheckInfo.LatestVer != "" { if config.Config.UpdateCheckInfo.LatestVer != "" {
if utils.ParseVersionNum(config.Config.UpdateCheckInfo.LatestVer) > utils.ParseVersionNum(config.AppVersion) { if utils.ParseVersionNum(config.Config.UpdateCheckInfo.LatestVer) > utils.ParseVersionNum(global.AppVersion) {
fmt.Printf("\n当前的软件版本为:%s, 现在有新版本 %s 可供更新,强烈推荐进行更新!(可以输入 update 命令进行更新)\n\n", fmt.Printf("\n当前的软件版本为:%s, 现在有新版本 %s 可供更新,强烈推荐进行更新!(可以输入 update 命令进行更新)\n\n",
config.AppVersion, config.Config.UpdateCheckInfo.LatestVer) global.AppVersion, config.Config.UpdateCheckInfo.LatestVer)
} }
} }
go func() { go func() {
@@ -415,7 +416,7 @@ func main() {
command.CmdQuota(), command.CmdQuota(),
// Token操作 // Token操作
command.CmdToken(), //command.CmdToken(),
// 切换工作目录 cd // 切换工作目录 cd
command.CmdCd(), command.CmdCd(),