aliyunpan/internal/config/pan_user.go

396 lines
11 KiB
Go
Raw Normal View History

2021-10-10 10:48:53 +08:00
// 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
//
2023-10-07 16:42:43 +08:00
// http://www.apache.org/licenses/LICENSE-2.0
2021-10-10 10:48:53 +08:00
//
// 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 config
import (
"fmt"
"github.com/tickstep/aliyunpan-api/aliyunpan"
"github.com/tickstep/aliyunpan-api/aliyunpan/apierror"
2024-03-02 00:55:46 +08:00
"github.com/tickstep/aliyunpan-api/aliyunpan_open"
"github.com/tickstep/aliyunpan-api/aliyunpan_open/openapi"
2024-03-03 14:02:05 +08:00
"github.com/tickstep/aliyunpan-api/aliyunpan_web"
2024-03-02 00:55:46 +08:00
"github.com/tickstep/aliyunpan/internal/functions/panlogin"
2021-10-30 22:53:08 +08:00
"github.com/tickstep/library-go/expires/cachemap"
2021-10-10 10:48:53 +08:00
"github.com/tickstep/library-go/logger"
"path"
"path/filepath"
2024-03-02 00:55:46 +08:00
"time"
2021-10-10 10:48:53 +08:00
)
type DriveInfo struct {
DriveId string `json:"driveId"`
DriveName string `json:"driveName"`
2022-01-30 22:10:46 +08:00
DriveTag string `json:"driveTag"`
2021-10-10 10:48:53 +08:00
}
type DriveInfoList []*DriveInfo
2022-01-02 18:44:45 +08:00
func (d DriveInfoList) GetFileDriveId() string {
2022-01-30 22:10:46 +08:00
for _, drive := range d {
2022-01-02 18:44:45 +08:00
if drive.DriveTag == "File" {
return drive.DriveId
}
}
return ""
}
2022-02-08 19:34:22 +08:00
func (d DriveInfoList) GetAlbumDriveId() string {
for _, drive := range d {
if drive.DriveTag == "Album" {
return drive.DriveId
}
}
return ""
}
2023-10-07 16:42:43 +08:00
func (d DriveInfoList) GetResourceDriveId() string {
for _, drive := range d {
if drive.DriveTag == "Resource" {
return drive.DriveId
}
}
return ""
}
2024-03-02 00:55:46 +08:00
// 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")
}
2021-10-10 10:48:53 +08:00
type PanUser struct {
2024-03-02 00:55:46 +08:00
// 用户信息
2021-10-10 10:48:53 +08:00
UserId string `json:"userId"`
2022-01-30 22:10:46 +08:00
Nickname string `json:"nickname"`
2021-10-10 10:48:53 +08:00
AccountName string `json:"accountName"`
2024-03-02 00:55:46 +08:00
// 文件(备份盘)
2022-01-30 22:10:46 +08:00
Workdir string `json:"workdir"`
2021-10-10 10:48:53 +08:00
WorkdirFileEntity aliyunpan.FileEntity `json:"workdirFileEntity"`
2023-10-07 16:42:43 +08:00
// 资源库
ResourceWorkdir string `json:"resourceWorkdir"`
ResourceWorkdirFileEntity aliyunpan.FileEntity `json:"resourceWorkdirFileEntity"`
// 相册
2022-01-30 22:10:46 +08:00
AlbumWorkdir string `json:"albumWorkdir"`
2021-10-10 10:48:53 +08:00
AlbumWorkdirFileEntity aliyunpan.FileEntity `json:"albumWorkdirFileEntity"`
2024-03-02 00:55:46 +08:00
// 用户网盘信息
2022-01-30 22:10:46 +08:00
ActiveDriveId string `json:"activeDriveId"`
DriveList DriveInfoList `json:"driveList"`
2021-10-10 10:48:53 +08:00
2024-03-02 00:55:46 +08:00
// 授权Token信息
TicketId string `json:"ticketId"`
WebapiToken *PanClientToken `json:"webapiToken"`
OpenapiToken *PanClientToken `json:"openapiToken"`
2021-10-10 10:48:53 +08:00
2024-03-02 00:55:46 +08:00
// API客户端
panClient *PanClient `json:"-"`
cacheOpMap cachemap.CacheOpMap `json:"-"`
2021-10-10 10:48:53 +08:00
}
type PanUserList []*PanUser
2024-03-02 00:55:46 +08:00
func SetupUserByCookie(openapiToken, webapiToken *PanClientToken, ticketId, userId, deviceId, deviceName, clientId, clientSecret string) (user *PanUser, err *apierror.ApiError) {
2021-10-10 10:48:53 +08:00
tryRefreshWebToken := true
2024-03-02 00:55:46 +08:00
tryRefreshOpenToken := true
loginHelper := panlogin.NewLoginHelper(DefaultTokenServiceWebHost)
2021-10-10 10:48:53 +08:00
2024-03-02 00:55:46 +08:00
if openapiToken == nil {
return nil, apierror.NewFailedApiError("openapi token is empty")
}
2024-04-01 22:46:24 +08:00
//if webapiToken == nil {
// return nil, apierror.NewFailedApiError("webapi token is empty")
//}
2024-03-02 00:55:46 +08:00
doOpenLoginAct:
// setup openapi client
openPanClient := aliyunpan_open.NewOpenPanClient(openapi.ApiConfig{
TicketId: ticketId,
UserId: userId,
ClientId: clientId,
ClientSecret: clientSecret,
}, openapi.ApiToken{
AccessToken: openapiToken.AccessToken,
ExpiredAt: openapiToken.Expired,
2024-03-02 22:10:54 +08:00
}, nil)
2024-03-02 00:55:46 +08:00
// open api token maybe expired
// check & refresh new one
openUserInfo, err := openPanClient.GetUserInfo()
if err != nil {
if err.Code == apierror.ApiCodeTokenExpiredCode && tryRefreshOpenToken {
tryRefreshOpenToken = false
2024-03-03 09:11:58 +08:00
wt, e := loginHelper.GetOpenapiNewToken(ticketId, userId, openapiToken.AccessToken)
2024-03-02 00:55:46 +08:00
if e != nil {
logger.Verboseln("get openapi token from server error: ", e)
return nil, apierror.NewFailedApiError("get new openapi token error, try login again")
}
if wt != nil {
openapiToken = &PanClientToken{
AccessToken: wt.AccessToken,
Expired: wt.Expired,
}
}
2024-03-02 21:22:02 +08:00
time.Sleep(time.Duration(1) * time.Second)
goto doOpenLoginAct
2024-03-02 00:55:46 +08:00
}
return nil, err
2021-10-10 10:48:53 +08:00
}
2024-03-02 00:55:46 +08:00
doWebLoginAct:
// setup webapi client
2024-03-02 21:22:02 +08:00
var webUserInfo *aliyunpan.UserInfo
var err2 *apierror.ApiError
2024-03-03 14:07:35 +08:00
var webPanClient *aliyunpan_web.WebPanClient
2024-03-02 21:22:02 +08:00
if webapiToken != nil && webapiToken.AccessToken != "" {
2024-03-03 14:02:05 +08:00
appConfig := aliyunpan_web.AppConfig{
2024-03-02 21:22:02 +08:00
AppId: "25dzX3vbYqktVxyX",
DeviceId: deviceId,
UserId: userId,
Nonce: 0,
PublicKey: "",
}
2024-03-03 14:07:35 +08:00
webPanClient = aliyunpan_web.NewWebPanClient(aliyunpan_web.WebLoginToken{
2024-03-02 21:22:02 +08:00
AccessTokenType: "Bearer",
AccessToken: webapiToken.AccessToken,
RefreshToken: "",
ExpiresIn: 7200,
ExpireTime: webapiToken.GetExpiredTimeCstStr(),
2024-03-03 14:02:05 +08:00
}, aliyunpan_web.AppLoginToken{}, appConfig, aliyunpan_web.SessionConfig{
2024-03-02 21:22:02 +08:00
DeviceName: deviceName,
ModelName: "Windows网页版",
})
// web api token maybe expired
// check & refresh new one
webUserInfo, err2 = webPanClient.GetUserInfo()
if err2 != nil {
if err2.Code == apierror.ApiCodeTokenExpiredCode && tryRefreshWebToken {
tryRefreshWebToken = false
2024-03-03 09:11:58 +08:00
wt, e := loginHelper.GetWebapiNewToken(ticketId, userId, webapiToken.AccessToken)
2024-03-02 21:22:02 +08:00
if e != nil {
logger.Verboseln("get web token from server error: ", e)
2024-03-02 00:55:46 +08:00
}
2024-03-02 21:22:02 +08:00
if wt != nil {
webapiToken = &PanClientToken{
AccessToken: wt.AccessToken,
Expired: wt.Expired,
}
}
time.Sleep(time.Duration(1) * time.Second)
2024-03-02 00:55:46 +08:00
goto doWebLoginAct
2021-10-10 10:48:53 +08:00
}
2024-03-02 21:22:02 +08:00
webPanClient = nil
//return nil, err2
}
// web create session
if webUserInfo != nil {
appConfig.UserId = webUserInfo.UserId
webPanClient.UpdateAppConfig(appConfig)
r, e := webPanClient.CreateSession(nil)
if e != nil {
logger.Verboseln("call CreateSession error in SetupUserByCookie: " + e.Error())
}
if r != nil && !r.Result {
logger.Verboseln("上传签名秘钥失败,可能是你账号登录的设备已超最大数量")
}
2021-10-10 10:48:53 +08:00
}
2024-03-02 00:55:46 +08:00
}
//
// setup PanUser
//
u := &PanUser{
WebapiToken: webapiToken,
OpenapiToken: openapiToken,
panClient: NewPanClient(webPanClient, openPanClient),
Workdir: "/",
WorkdirFileEntity: *aliyunpan.NewFileEntityForRootDir(),
}
2024-03-02 22:10:54 +08:00
u.PanClient().OpenapiPanClient().SetAccessTokenRefreshCallback(func(userId string, newToken openapi.ApiToken) error {
logger.Verboseln("openapi token refresh, update for user")
u.OpenapiToken = &PanClientToken{
AccessToken: newToken.AccessToken,
Expired: newToken.ExpiredAt,
}
return nil
})
2024-03-02 00:55:46 +08:00
// setup user info
2021-10-10 10:48:53 +08:00
name := "Unknown"
2024-03-02 00:55:46 +08:00
if openUserInfo != nil {
// fill userId for client
u.PanClient().OpenapiPanClient().UpdateUserId(openUserInfo.UserId)
2024-03-02 21:22:02 +08:00
if u.PanClient().WebapiPanClient() != nil {
u.PanClient().WebapiPanClient().UpdateUserId(openUserInfo.UserId)
}
2021-10-10 10:48:53 +08:00
// update user
2024-03-02 00:55:46 +08:00
if openUserInfo.Nickname != "" {
name = openUserInfo.Nickname
}
u.UserId = openUserInfo.UserId
2021-10-10 10:48:53 +08:00
u.Nickname = name
2024-03-02 00:55:46 +08:00
u.AccountName = openUserInfo.UserName
2021-10-10 10:48:53 +08:00
// default file drive
if u.ActiveDriveId == "" {
2024-03-02 00:55:46 +08:00
u.ActiveDriveId = openUserInfo.FileDriveId
2021-10-10 10:48:53 +08:00
}
// drive list
u.DriveList = DriveInfoList{
2024-03-02 00:55:46 +08:00
{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: "相册"})
2021-10-10 10:48:53 +08:00
}
} else {
// error, maybe the token has expired
2024-03-02 00:55:46 +08:00
return nil, apierror.NewFailedApiError("cannot get user info, the token has expired. please login again")
2023-02-16 22:25:09 +08:00
}
2024-03-02 00:55:46 +08:00
// return user
2021-10-10 10:48:53 +08:00
return u, nil
}
2024-03-02 00:55:46 +08:00
func (pu *PanUser) PanClient() *PanClient {
2021-10-10 10:48:53 +08:00
return pu.panClient
}
2024-03-03 23:20:27 +08:00
func (pu *PanUser) UpdateClient(openClient *aliyunpan_open.OpenPanClient, webClient *aliyunpan_web.WebPanClient) {
if pu.panClient == nil {
pu.panClient = &PanClient{
webapiPanClient: webClient,
openapiPanClient: openClient,
}
} else {
pu.panClient.webapiPanClient = webClient
pu.panClient.openapiPanClient = openClient
}
}
2021-10-10 10:48:53 +08:00
// PathJoin 合并工作目录和相对路径p, 若p为绝对路径则忽略
func (pu *PanUser) PathJoin(driveId, p string) string {
if path.IsAbs(p) {
return p
}
wd := "/"
di := pu.GetDriveById(driveId)
if di != nil {
if di.IsFileDrive() {
wd = pu.Workdir
2023-10-07 16:42:43 +08:00
} else if di.IsResourceDrive() {
wd = pu.ResourceWorkdir
2021-10-10 10:48:53 +08:00
} else if di.IsAlbumDrive() {
wd = pu.AlbumWorkdir
}
}
return path.Join(wd, p)
}
func (pu *PanUser) FreshWorkdirInfo() {
if pu.IsFileDriveActive() {
fe, err := pu.PanClient().OpenapiPanClient().FileInfoById(pu.ActiveDriveId, pu.WorkdirFileEntity.FileId)
2021-10-10 10:48:53 +08:00
if err != nil {
logger.Verboseln("刷新工作目录信息失败")
return
}
pu.WorkdirFileEntity = *fe
} else if pu.IsAlbumDriveActive() {
fe, err := pu.PanClient().OpenapiPanClient().FileInfoById(pu.ActiveDriveId, pu.AlbumWorkdirFileEntity.FileId)
2021-10-10 10:48:53 +08:00
if err != nil {
logger.Verboseln("刷新工作目录信息失败")
return
}
pu.AlbumWorkdirFileEntity = *fe
}
}
// GetSavePath 根据提供的网盘文件路径 panpath, 返回本地储存路径,
// 返回绝对路径, 获取绝对路径出错时才返回相对路径...
func (pu *PanUser) GetSavePath(filePanPath string) string {
dirStr := filepath.Join(Config.SaveDir, fmt.Sprintf("%s", pu.UserId), filePanPath)
dir, err := filepath.Abs(dirStr)
if err != nil {
dir = filepath.Clean(dirStr)
}
return dir
}
func (pu *PanUser) GetDriveByTag(tag string) *DriveInfo {
2022-01-30 22:10:46 +08:00
for _, item := range pu.DriveList {
2021-10-10 10:48:53 +08:00
if item.DriveTag == tag {
return item
}
}
return nil
}
func (pu *PanUser) GetDriveById(id string) *DriveInfo {
2022-01-30 22:10:46 +08:00
for _, item := range pu.DriveList {
2021-10-10 10:48:53 +08:00
if item.DriveId == id {
return item
}
}
return nil
}
func (pu *PanUser) GetActiveDriveInfo() *DriveInfo {
2022-01-30 22:10:46 +08:00
for _, item := range pu.DriveList {
2021-10-10 10:48:53 +08:00
if item.DriveId == pu.ActiveDriveId {
return item
}
}
return nil
}
func (pu *PanUser) IsFileDriveActive() bool {
d := pu.GetActiveDriveInfo()
return d != nil && d.IsFileDrive()
}
func (pu *PanUser) IsAlbumDriveActive() bool {
d := pu.GetActiveDriveInfo()
return d != nil && d.IsAlbumDrive()
}
2023-10-07 16:42:43 +08:00
func (pu *PanUser) IsResourceDriveActive() bool {
d := pu.GetActiveDriveInfo()
return d != nil && d.IsResourceDrive()
}
2021-10-10 10:48:53 +08:00
func (di *DriveInfo) IsFileDrive() bool {
return di.DriveTag == "File"
}
func (di *DriveInfo) IsAlbumDrive() bool {
return di.DriveTag == "Album"
2022-01-30 22:10:46 +08:00
}
2023-10-07 16:42:43 +08:00
func (di *DriveInfo) IsResourceDrive() bool {
return di.DriveTag == "Resource"
}