mirror of https://github.com/Xhofe/alist
				
				
				
			
		
			
				
	
	
		
			199 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			Go
		
	
	
			
		
		
	
	
			199 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			Go
		
	
	
package google
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"github.com/Xhofe/alist/conf"
 | 
						|
	"github.com/Xhofe/alist/drivers/base"
 | 
						|
	"github.com/Xhofe/alist/model"
 | 
						|
	"github.com/Xhofe/alist/utils"
 | 
						|
	"github.com/go-resty/resty/v2"
 | 
						|
	log "github.com/sirupsen/logrus"
 | 
						|
	"path/filepath"
 | 
						|
	"strconv"
 | 
						|
	"time"
 | 
						|
)
 | 
						|
 | 
						|
type TokenError struct {
 | 
						|
	Error            string `json:"error"`
 | 
						|
	ErrorDescription string `json:"error_description"`
 | 
						|
}
 | 
						|
 | 
						|
func (driver GoogleDrive) RefreshToken(account *model.Account) error {
 | 
						|
	url := "https://www.googleapis.com/oauth2/v4/token"
 | 
						|
	if account.APIProxyUrl != "" {
 | 
						|
		url = fmt.Sprintf("%s/%s", account.APIProxyUrl, url)
 | 
						|
	}
 | 
						|
	var resp base.TokenResp
 | 
						|
	var e TokenError
 | 
						|
	res, err := base.RestyClient.R().SetResult(&resp).SetError(&e).
 | 
						|
		SetFormData(map[string]string{
 | 
						|
			"client_id":     account.ClientId,
 | 
						|
			"client_secret": account.ClientSecret,
 | 
						|
			"refresh_token": account.RefreshToken,
 | 
						|
			"grant_type":    "refresh_token",
 | 
						|
		}).Post(url)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	log.Debug(res.String())
 | 
						|
	if e.Error != "" {
 | 
						|
		return fmt.Errorf(e.Error)
 | 
						|
	}
 | 
						|
	account.AccessToken = resp.AccessToken
 | 
						|
	account.Status = "work"
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
type File struct {
 | 
						|
	Id            string     `json:"id"`
 | 
						|
	Name          string     `json:"name"`
 | 
						|
	MimeType      string     `json:"mimeType"`
 | 
						|
	ModifiedTime  *time.Time `json:"modifiedTime"`
 | 
						|
	Size          string     `json:"size"`
 | 
						|
	ThumbnailLink string     `json:"thumbnailLink"`
 | 
						|
}
 | 
						|
 | 
						|
func (driver GoogleDrive) IsDir(mimeType string) bool {
 | 
						|
	return mimeType == "application/vnd.google-apps.folder" || mimeType == "application/vnd.google-apps.shortcut"
 | 
						|
}
 | 
						|
 | 
						|
func (driver GoogleDrive) FormatFile(file *File, account *model.Account) *model.File {
 | 
						|
	f := &model.File{
 | 
						|
		Id:        file.Id,
 | 
						|
		Name:      file.Name,
 | 
						|
		Driver:    driver.Config().Name,
 | 
						|
		UpdatedAt: file.ModifiedTime,
 | 
						|
		Url:       "",
 | 
						|
	}
 | 
						|
	if driver.IsDir(file.MimeType) {
 | 
						|
		f.Type = conf.FOLDER
 | 
						|
	} else {
 | 
						|
		size, _ := strconv.ParseInt(file.Size, 10, 64)
 | 
						|
		f.Size = size
 | 
						|
		f.Type = utils.GetFileType(filepath.Ext(file.Name))
 | 
						|
	}
 | 
						|
	if file.ThumbnailLink != "" {
 | 
						|
		if account.DownProxyUrl != "" {
 | 
						|
			f.Thumbnail = fmt.Sprintf("%s/%s", account.DownProxyUrl, file.ThumbnailLink)
 | 
						|
		} else {
 | 
						|
			f.Thumbnail = file.ThumbnailLink
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return f
 | 
						|
}
 | 
						|
 | 
						|
type Files struct {
 | 
						|
	NextPageToken string `json:"nextPageToken"`
 | 
						|
	Files         []File `json:"files"`
 | 
						|
}
 | 
						|
 | 
						|
type Error struct {
 | 
						|
	Error struct {
 | 
						|
		Errors []struct {
 | 
						|
			Domain       string `json:"domain"`
 | 
						|
			Reason       string `json:"reason"`
 | 
						|
			Message      string `json:"message"`
 | 
						|
			LocationType string `json:"location_type"`
 | 
						|
			Location     string `json:"location"`
 | 
						|
		}
 | 
						|
		Code    int    `json:"code"`
 | 
						|
		Message string `json:"message"`
 | 
						|
	} `json:"error"`
 | 
						|
}
 | 
						|
 | 
						|
func (driver GoogleDrive) GetFiles(id string, account *model.Account) ([]File, error) {
 | 
						|
	pageToken := "first"
 | 
						|
	res := make([]File, 0)
 | 
						|
	for pageToken != "" {
 | 
						|
		if pageToken == "first" {
 | 
						|
			pageToken = ""
 | 
						|
		}
 | 
						|
		var resp Files
 | 
						|
		orderBy := "folder,name,modifiedTime desc"
 | 
						|
		if account.OrderBy != "" {
 | 
						|
			orderBy = account.OrderBy + " " + account.OrderDirection
 | 
						|
		}
 | 
						|
		query := map[string]string{
 | 
						|
			"orderBy":  orderBy,
 | 
						|
			"fields":   "files(id,name,mimeType,size,modifiedTime,thumbnailLink),nextPageToken",
 | 
						|
			"pageSize": "1000",
 | 
						|
			"q":        fmt.Sprintf("'%s' in parents and trashed = false", id),
 | 
						|
			//"includeItemsFromAllDrives": "true",
 | 
						|
			//"supportsAllDrives":         "true",
 | 
						|
			"pageToken": pageToken,
 | 
						|
		}
 | 
						|
		_, err := driver.Request("https://www.googleapis.com/drive/v3/files",
 | 
						|
			base.Get, nil, query, nil, nil, &resp, account)
 | 
						|
		if err != nil {
 | 
						|
			return nil, err
 | 
						|
		}
 | 
						|
		pageToken = resp.NextPageToken
 | 
						|
		res = append(res, resp.Files...)
 | 
						|
	}
 | 
						|
	return res, nil
 | 
						|
}
 | 
						|
 | 
						|
func (driver GoogleDrive) Request(url string, method int, headers, query, form map[string]string, data interface{}, resp interface{}, account *model.Account) ([]byte, error) {
 | 
						|
	rawUrl := url
 | 
						|
	if account.APIProxyUrl != "" {
 | 
						|
		url = fmt.Sprintf("%s/%s", account.APIProxyUrl, url)
 | 
						|
	}
 | 
						|
	req := base.RestyClient.R()
 | 
						|
	req.SetHeader("Authorization", "Bearer "+account.AccessToken)
 | 
						|
	req.SetQueryParam("includeItemsFromAllDrives", "true")
 | 
						|
	req.SetQueryParam("supportsAllDrives", "true")
 | 
						|
	if headers != nil {
 | 
						|
		req.SetHeaders(headers)
 | 
						|
	}
 | 
						|
	if query != nil {
 | 
						|
		req.SetQueryParams(query)
 | 
						|
	}
 | 
						|
	if form != nil {
 | 
						|
		req.SetFormData(form)
 | 
						|
	}
 | 
						|
	if data != nil {
 | 
						|
		req.SetBody(data)
 | 
						|
	}
 | 
						|
	if resp != nil {
 | 
						|
		req.SetResult(resp)
 | 
						|
	}
 | 
						|
	var res *resty.Response
 | 
						|
	var err error
 | 
						|
	var e Error
 | 
						|
	req.SetError(&e)
 | 
						|
	switch method {
 | 
						|
	case base.Get:
 | 
						|
		res, err = req.Get(url)
 | 
						|
	case base.Post:
 | 
						|
		res, err = req.Post(url)
 | 
						|
	case base.Delete:
 | 
						|
		res, err = req.Delete(url)
 | 
						|
	case base.Patch:
 | 
						|
		res, err = req.Patch(url)
 | 
						|
	case base.Put:
 | 
						|
		res, err = req.Put(url)
 | 
						|
	default:
 | 
						|
		return nil, base.ErrNotSupport
 | 
						|
	}
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	log.Debug(res.String())
 | 
						|
	if e.Error.Code != 0 {
 | 
						|
		if e.Error.Code == 401 {
 | 
						|
			err = driver.RefreshToken(account)
 | 
						|
			if err != nil {
 | 
						|
				_ = model.SaveAccount(account)
 | 
						|
				return nil, err
 | 
						|
			}
 | 
						|
			return driver.Request(rawUrl, method, headers, query, form, data, resp, account)
 | 
						|
		}
 | 
						|
		return nil, fmt.Errorf("%s: %v", e.Error.Message, e.Error.Errors)
 | 
						|
	}
 | 
						|
	return res.Body(), nil
 | 
						|
}
 | 
						|
 | 
						|
func init() {
 | 
						|
	base.RegisterDriver(&GoogleDrive{})
 | 
						|
}
 |