Initial commit

This commit is contained in:
微凉
2020-12-24 01:39:45 +08:00
commit 430b4cf723
30 changed files with 1223 additions and 0 deletions

74
alidrive/auth.go Normal file
View File

@ -0,0 +1,74 @@
package alidrive
import (
"encoding/json"
"fmt"
"github.com/Xhofe/alist/conf"
"github.com/Xhofe/alist/utils"
log "github.com/sirupsen/logrus"
)
func TokenLogin() (*TokenLoginResp, error) {
log.Infof("尝试使用token登录...")
url:="https://auth.aliyundrive.com/v2/oauth/token_login"
req:=TokenLoginReq{Token:conf.Conf.AliDrive.LoginToken}
log.Debugf("token_login_req:%v",req)
var tokenLogin TokenLoginResp
if body, err := DoPost(url, req,false); err != nil {
log.Errorf("tokenLogin-doPost出错:%s",err.Error())
return nil,err
}else {
if err = json.Unmarshal(body,&tokenLogin);err!=nil {
log.Errorf("解析json[%s]出错:%s",string(body),err.Error())
return nil,err
}
}
if tokenLogin.IsAvailable() {
return &tokenLogin,nil
}
return nil,fmt.Errorf("登录token失效,请更换:%s",tokenLogin.Message)
}
func GetToken(tokenLogin *TokenLoginResp) (*TokenResp,error) {
log.Infof("获取API token...")
url:="https://websv.aliyundrive.com/token/get"
code:=utils.GetCode(tokenLogin.Goto)
if code == "" {
return nil,fmt.Errorf("获取code出错")
}
req:=GetTokenReq{Code:code}
var token TokenResp
if body, err := DoPost(url, req,false); err != nil {
log.Errorf("tokenLogin-doPost出错:%s",err.Error())
return nil,err
}else {
if err = json.Unmarshal(body,&token);err!=nil {
log.Errorf("解析json[%s]出错:%s",string(body),err.Error())
log.Errorf("此处json解析失败应该是code失效")
return nil,fmt.Errorf("code失效")
}
}
return &token,nil
}
func RefreshToken() bool {
log.Infof("刷新token...")
url:="https://websv.aliyundrive.com/token/refresh"
req:=RefreshTokenReq{RefreshToken:conf.Conf.AliDrive.RefreshToken}
var token TokenResp
if body, err := DoPost(url, req,false); err != nil {
log.Errorf("tokenLogin-doPost出错:%s",err.Error())
return false
}else {
if err = json.Unmarshal(body,&token);err!=nil {
log.Errorf("解析json[%s]出错:%s",string(body),err.Error())
log.Errorf("此处json解析失败应该是refresh_token失效")
return false
}
}
//刷新成功 更新token
conf.Conf.AliDrive.AccessToken=token.AccessToken
conf.Conf.AliDrive.RefreshToken=token.RefreshToken
conf.Authorization=token.TokenType+"\t"+token.AccessToken
return true
}

5
alidrive/const.go Normal file
View File

@ -0,0 +1,5 @@
package alidrive
var (
User *UserInfo
)

46
alidrive/req_bean.go Normal file
View File

@ -0,0 +1,46 @@
package alidrive
type ListReq struct {
DriveId string `json:"drive_id"`
Fields string `json:"fields"`
ImageThumbnailProcess string `json:"image_thumbnail_process"`
ImageUrlProcess string `json:"image_url_process"`
Limit int `json:"limit"`
Marker string `json:"marker"`
OrderBy string `json:"order_by"`
OrderDirection string `json:"order_direction"`
ParentFileId string `json:"parent_file_id"`
VideoThumbnailProcess string `json:"video_thumbnail_process"`
}
type GetReq struct {
DriveId string `json:"drive_id"`
FileId string `json:"file_id"`
ImageThumbnailProcess string `json:"image_thumbnail_process"`
VideoThumbnailProcess string `json:"video_thumbnail_process"`
}
type SearchReq struct {
DriveId string `json:"drive_id"`
ImageThumbnailProcess string `json:"image_thumbnail_process"`
ImageUrlProcess string `json:"image_url_process"`
Limit int `json:"limit"`
Marker string `json:"marker"`
OrderBy string `json:"order_by"`//"type ASC,updated_at DESC"
Query string `json:"query"`// "name match '测试文件'"
VideoThumbnailProcess string `json:"video_thumbnail_process"`
}
type TokenLoginReq struct {
Token string `json:"token"`
}
type GetTokenReq struct {
Code string `json:"code"`
}
type RefreshTokenReq struct {
RefreshToken string `json:"refresh_token"`
}

200
alidrive/request.go Normal file
View File

@ -0,0 +1,200 @@
package alidrive
import (
"bytes"
"encoding/json"
"fmt"
"github.com/Xhofe/alist/conf"
log "github.com/sirupsen/logrus"
"io/ioutil"
"net/http"
"strings"
"time"
)
func GetFile(fileId string) (*File, error) {
url:=conf.Conf.AliDrive.ApiUrl+"/file/get"
req:=GetReq{
DriveId: User.DefaultDriveId,
FileId: fileId,
ImageThumbnailProcess: conf.ImageThumbnailProcess,
VideoThumbnailProcess: conf.VideoThumbnailProcess,
}
var file File
if body, err := DoPost(url, req,true); err != nil {
log.Errorf("doPost出错:%s",err.Error())
return nil,err
}else {
if err = json.Unmarshal(body,&file);err !=nil {
log.Errorf("解析json[%s]出错:%s",string(body),err.Error())
return nil,err
}
}
if file.IsAvailable() {
return &file,nil
}
if file.Code==conf.AccessTokenInvalid {
if RefreshToken() {
return GetFile(fileId)
}
}
return nil,fmt.Errorf(file.Message)
}
func Search(key string,limit int, marker string) (*Files, error) {
url:=conf.Conf.AliDrive.ApiUrl+"/file/search"
req:=SearchReq{
DriveId: User.DefaultDriveId,
ImageThumbnailProcess: conf.ImageThumbnailProcess,
ImageUrlProcess: conf.ImageUrlProcess,
Limit: limit,
Marker: marker,
OrderBy: conf.OrderSearch,
Query: fmt.Sprintf("name match '%s'",key),
VideoThumbnailProcess: conf.VideoThumbnailProcess,
}
var files Files
if body, err := DoPost(url, req,true); err != nil {
log.Errorf("doPost出错:%s",err.Error())
return nil,err
}else {
if err = json.Unmarshal(body,&files);err !=nil {
log.Errorf("解析json[%s]出错:%s",string(body),err.Error())
return nil,err
}
}
if files.IsAvailable() {
return &files,nil
}
if files.Code==conf.AccessTokenInvalid {
if RefreshToken() {
return Search(key,limit,marker)
}
}
return nil,fmt.Errorf(files.Message)
}
func GetRoot(limit int,marker string,orderBy string,orderDirection string) (*Files,error) {
return GetList(conf.Conf.AliDrive.RootFolder,limit,marker,orderBy,orderDirection)
}
func GetList(parent string,limit int,marker string,orderBy string,orderDirection string) (*Files,error) {
url:=conf.Conf.AliDrive.ApiUrl+"/file/list"
req:=ListReq{
DriveId: User.DefaultDriveId,
Fields: "*",
ImageThumbnailProcess: conf.ImageThumbnailProcess,
ImageUrlProcess: conf.ImageUrlProcess,
Limit: limit,
Marker: marker,
OrderBy: orderBy,
OrderDirection: orderDirection,
ParentFileId: parent,
VideoThumbnailProcess: conf.VideoThumbnailProcess,
}
var files Files
if body, err := DoPost(url, req,true); err != nil {
log.Errorf("doPost出错:%s",err.Error())
return nil,err
}else {
if err = json.Unmarshal(body,&files);err !=nil {
log.Errorf("解析json[%s]出错:%s",string(body),err.Error())
return nil,err
}
}
if files.IsAvailable() {
return &files,nil
}
if files.Code==conf.AccessTokenInvalid {
if RefreshToken() {
return GetRoot(limit,marker,orderBy,orderDirection)
}
}
return nil,fmt.Errorf(files.Message)
}
func GetUserInfo() (*UserInfo,error) {
url:=conf.Conf.AliDrive.ApiUrl+"/user/get"
var user UserInfo
if body, err := DoPost(url, map[string]interface{}{},true); err != nil {
log.Errorf("doPost出错:%s",err.Error())
return nil,err
}else {
if err = json.Unmarshal(body,&user);err !=nil {
log.Errorf("解析json[%s]出错:%s",string(body),err.Error())
return nil,err
}
}
if user.IsAvailable() {
return &user,nil
}
if user.Code==conf.AccessTokenInvalid {
if RefreshToken() {
return GetUserInfo()
}
}
return nil,fmt.Errorf(user.Message)
}
func DoPost(url string,request interface{},auth bool) (body []byte, err error) {
var(
resp *http.Response
)
requestBody := new(bytes.Buffer)
err = json.NewEncoder(requestBody).Encode(request)
if err !=nil {
log.Errorf("创建requestBody出错:%s",err.Error())
}
req,err:=http.NewRequest("POST",url,requestBody)
log.Debugf("do_post_req:%v",req)
if err != nil {
log.Errorf("创建request出错:%s",err.Error())
return
}
if auth {
req.Header.Set("authorization",conf.Authorization)
}
req.Header.Add("content-type","application/json")
req.Header.Add("user-agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36")
req.Header.Add("origin","https://aliyundrive.com")
req.Header.Add("accept","*/*")
req.Header.Add("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3")
req.Header.Add("Connection", "keep-alive")
for retryCount := 3; retryCount >= 0; retryCount-- {
if resp,err=conf.Client.Do(req);err!=nil&&strings.Contains(err.Error(),"timeout") {
<- time.After(time.Second)
}else {
break
}
}
if err!=nil {
log.Errorf("请求阿里云盘api时出错:%s",err.Error())
return
}
if body, err = ioutil.ReadAll(resp.Body); err != nil {
log.Errorf("读取api返回内容失败")
}
return
}
func GetPaths(fileId string) (*[]Path,error) {
paths:=make([]Path,0)
for fileId != conf.Conf.AliDrive.RootFolder && fileId != "root" {
file,err:=GetFile(fileId)
if err !=nil {
log.Errorf("获取path出错:%s",err.Error())
return nil,err
}
paths=append(paths,Path{
Name: file.Name,
FileId: file.FileId,
})
fileId=file.ParentFileId
}
paths=append(paths, Path{
Name: "Root",
FileId: "root",
})
return &paths,nil
}

135
alidrive/resp_bean.go Normal file
View File

@ -0,0 +1,135 @@
package alidrive
import (
log "github.com/sirupsen/logrus"
"io/ioutil"
"net/http"
"strings"
"time"
)
type RespError struct {
Code string `json:"code"`
Message string `json:"message"`
}
type UserInfo struct {
RespError
DomainId string `json:"domain_id"`
UserId string `json:"user_id"`
Avatar string `json:"avatar"`
CreatedAt int `json:"created_at"`
UpdatedAt int `json:"updated_at"`
Email string `json:"email"`
NickName string `json:"nick_name"`
Phone string `json:"phone"`
Role string `json:"role"`
Status string `json:"status"`
UserName string `json:"user_name"`
Description string `json:"description"`
DefaultDriveId string `json:"default_drive_id"`
UserData map[string]interface{} `json:"user_data"`
}
type Files struct {
RespError
Items []File `json:"items"`
NextMarker string `json:"next_marker"`
Readme string `json:"readme"`
Paths []Path `json:"paths"`
}
type Path struct {
Name string `json:"name"`
FileId string `json:"file_id"`
}
type File struct {
RespError
DriveId string `json:"drive_id"`
CreatedAt *time.Time `json:"created_at"`
DomainId string `json:"domain_id"`
EncryptMode string `json:"encrypt_mode"`
FileExtension string `json:"file_extension"`
FileId string `json:"file_id"`
Hidden bool `json:"hidden"`
Name string `json:"name"`
ParentFileId string `json:"parent_file_id"`
Starred bool `json:"starred"`
Status string `json:"status"`
Type string `json:"type"`
UpdatedAt *time.Time `json:"updated_at"`
// 文件多出部分
Category string `json:"category"`
ContentHash string `json:"content_hash"`
ContentHashName string `json:"content_hash_name"`
ContentType string `json:"content_type"`
Crc64Hash string `json:"crc_64_hash"`
DownloadUrl string `json:"download_url"`
PunishFlag int `json:"punish_flag"`
Size int `json:"size"`
Thumbnail string `json:"thumbnail"`
Url string `json:"url"`
ImageMediaMetadata map[string]interface{} `json:"image_media_metadata"`
Paths []Path `json:"paths"`
}
func (resp *RespError) IsAvailable() bool {
return resp.Code == ""
}
type TokenLoginResp struct {
RespError
Goto string `json:"goto"`
}
type TokenResp struct {
RespError
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
ExpiresIn int `json:"expires_in"`
TokenType string `json:"token_type"`
UserInfo
DefaultSboxDriveId string `json:"default_sbox_drive_id"`
ExpireTime *time.Time `json:"expire_time"`
State string `json:"state"`
ExistLink []interface{} `json:"exist_link"`
NeedLink bool `json:"need_link"`
PinSetup bool `json:"pin_setup"`
IsFirstLogin bool `json:"is_first_login"`
NeedRpVerify bool `json:"need_rp_verify"`
DeviceId string `json:"device_id"`
}
func HasPassword(files *Files) string {
fileList := files.Items
for _, file := range fileList {
if strings.HasPrefix(file.Name, ".password-") {
return file.Name[10:]
}
}
return ""
}
func HasReadme(files *Files) string {
fileList := files.Items
for _, file := range fileList {
if file.Name == "Readme.md" {
resp, err := http.Get(file.Url)
if err != nil {
log.Errorf("Get Readme出错:%s", err.Error())
return ""
}
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Errorf("读取 Readme出错:%s", err.Error())
return ""
}
return string(data)
}
}
return ""
}