docxTemplater/gdisk/api.go
2023-08-17 13:12:22 +05:00

470 lines
12 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package gdisk
import (
"bytes"
"context"
"fmt"
"io"
"log"
"net/http"
"os"
"strings"
"github.com/pkg/errors"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"google.golang.org/api/drive/v3"
"google.golang.org/api/option"
"penahub.gitlab.yandexcloud.net/backend/templategen/tools"
)
const (
DefaultDir = "TemplateGenerator"
TemplateDir = "templates"
SaveDir = "saved"
MimeTypeDocx = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
MimeTypeGoogle = "application/vnd.google-apps.document"
)
type Client struct {
App *ClientApp
HTTPClient *http.Client
Service *drive.Service
Token *oauth2.Token
}
type ClientApp struct {
Config *oauth2.Config
}
func NewClientApp(credentials string) (*ClientApp, error) {
b, err := os.ReadFile(credentials)
if err != nil {
return nil, errors.Wrap(err, "NewClientApp.ReadFile")
}
config, err := google.ConfigFromJSON(b,
drive.DriveScope,
drive.DriveMetadataScope,
)
if err != nil {
return nil, errors.Wrap(err, "NewClientApp.ConfigFromJSON")
}
return &ClientApp{Config: config}, nil
}
func (ca *ClientApp) GenerateOAuthURL(penaID, redirectURL string) (string, error) {
state, err := tools.EncryptTokenAES(tools.StateToken{
PenaID: penaID,
Service: "google",
RedirectURL: redirectURL,
})
if err != nil {
return "", errors.Wrap(err, "GenerateOAuthURL.Encrypt")
}
return ca.Config.AuthCodeURL(state, oauth2.AccessTypeOffline, oauth2.ApprovalForce), nil
}
func (ca *ClientApp) RefreshToken(ctx context.Context, oldToken *oauth2.Token) (*oauth2.Token, error) {
token, err := ca.Config.TokenSource(ctx, oldToken).Token()
if err != nil {
return nil, errors.Wrap(err, "RefreshToken")
}
return token, nil
}
func (ca *ClientApp) NewClient(ctx context.Context, token *oauth2.Token) (*Client, error) {
client := ca.Config.Client(ctx, token)
service, err := drive.NewService(ctx, option.WithHTTPClient(client))
if err != nil {
return nil, errors.Wrap(err, "NewClient.NewService")
}
return &Client{
App: ca,
HTTPClient: client,
Service: service,
Token: token,
}, nil
}
func (ca *ClientApp) GetToken(ctx context.Context, authCode string) (*oauth2.Token, error) {
return ca.Config.Exchange(ctx, authCode)
}
func (c *Client) SetToken(token oauth2.Token) {
c.Token = &token
}
func (c *Client) GetDisk(ctx context.Context) {
service, err := drive.NewService(ctx, option.WithHTTPClient(c.HTTPClient))
if err != nil {
log.Println(errors.Wrap(err, "GetDisk.NewService"))
return
}
about, err := service.About.Get().Fields("storageQuota", "user", "exportFormats", "maxImportSizes", "maxUploadSize").Do()
if err != nil {
log.Println(errors.Wrap(err, "GetDisk.ServiceAboutGet"))
return
}
fmt.Printf("srv.About %+v \r\n", about.User)
dl, err := service.Drives.List().Do()
if err != nil {
log.Println(errors.Wrap(err, "GetDisk.ServiceDriveListDo"))
return
}
fmt.Println("DRIVES ________________________")
for _, drive := range dl.Drives {
fmt.Println(drive)
}
}
// GetUserInfo - получить информацию о пользователе Google.
func (c *Client) GetUserInfo(ctx context.Context) (*drive.User, error) {
service, err := drive.NewService(ctx, option.WithHTTPClient(c.HTTPClient))
if err != nil {
return nil, errors.Wrap(err, "GetUserInfo.NewService")
}
about, err := service.About.Get().Fields("user").Do()
if err != nil {
return nil, errors.Wrap(err, "GetUserInfo.ServiceDo")
}
if about == nil {
return nil, errors.Wrap(errors.New("got empty about"), "GetUserInfo")
}
if about.User == nil {
return nil, errors.Wrap(errors.New("got empty about.User"), "GetUserInfo")
}
return about.User, nil
}
// GetResourcesByName - получить информацию о ресурсе.
func (c *Client) GetResourcesByName(name, parentID string) (*drive.FileList, error) {
query := "name = '" + name + "' and trashed = false"
if parentID != "" {
query += "and '" + parentID + "' in parents"
}
fl, err := c.Service.Files.List().
Q(query).
Do()
if err != nil {
if strings.Contains(err.Error(), "404") {
return nil, nil
}
return nil, errors.Wrap(err, "GetResourcesByName.ServiceFileListDo")
}
return fl, nil
}
// GetResources - получить список файлов и папок ресурса по его id
// Если id не указан, то принимается значение 'root'.
func (c *Client) GetResources(id string) (*drive.FileList, error) {
if id == "" {
id = "root"
}
query := fmt.Sprintf("trashed = false and '%v' in parents", id)
fl, err := c.Service.Files.List().
Q(query).
Do()
if err != nil {
if strings.Contains(err.Error(), "404") {
return nil, nil
}
return nil, errors.Wrap(err, "GetResources.ServiceFileListDo")
}
return fl, nil
}
// PutResources - создание папки.
func (c *Client) PutResources(name, parentID string) (*drive.File, error) {
queryFile := &drive.File{Name: name, MimeType: "application/vnd.google-apps.folder", IsAppAuthorized: true}
if parentID != "" {
queryFile.Parents = []string{parentID}
}
f, err := c.Service.Files.Create(queryFile).Do()
if err != nil {
return nil, errors.Wrap(err, "PutResources.ServiceFileListDo")
}
return f, nil
}
func (c *Client) DeleteResources(id string) error {
err := c.Service.Files.Delete(id).Do()
return errors.Wrap(err, "DeleteResources")
}
// UploadFile - отправить файл в диск.
func (c *Client) UploadFile(filepath, mimetype, parentID string) (string, string, error) {
file, err := os.Open(filepath)
defer func() {
if err = file.Close(); err != nil {
log.Println("ERROR", errors.Wrap(err, "UploadFile.FileClose"))
}
}()
if err != nil {
return "", "", errors.Wrap(err, "UploadFile.OsOpen")
}
filename := strings.Split(file.Name(), "/")
queryFile := &drive.File{
Name: filename[len(filename)-1],
MimeType: mimetype,
IsAppAuthorized: true,
}
if parentID != "" {
queryFile.Parents = []string{parentID}
}
fileData, err := c.Service.Files.Create(queryFile).Media(file).Do()
if err != nil {
return "", "", errors.Wrap(err, "UploadFile.ServiceFilesCreate")
}
return fileData.Id, fileData.ExportLinks[mimetype], nil
}
func (c *Client) UploadFileBytes(file []byte, filename, mimetype, parentID string) (string, string, error) {
queryFile := &drive.File{
Name: filename,
MimeType: mimetype,
IsAppAuthorized: true,
}
if parentID != "" {
queryFile.Parents = []string{parentID}
}
fileData, err := c.Service.Files.Create(queryFile).Media(bytes.NewReader(file)).Do()
if err != nil {
return "", "", errors.Wrap(err, "UploadFileBytes.ServiceFilesCreateDo")
}
return fileData.Id, fileData.ExportLinks[mimetype], nil
}
func (c *Client) DownloadFile(filepath, fileID string) error {
file, err := c.Service.Files.Get(fileID).Do()
if err != nil {
return errors.Wrap(err, "DownloadFile.ServiceFilesGetDo")
}
var resp *http.Response
if file.MimeType == MimeTypeGoogle {
resp, err = c.Service.Files.Export(fileID, MimeTypeDocx).
Fields("exportFormat", "docx").
Download()
err = errors.Wrap(err, "DownloadFile.Export")
} else {
resp, err = c.Service.Files.Get(fileID).Download()
err = errors.Wrap(err, "DownloadFile.Download")
}
if err != nil {
return err
}
defer func() {
if err = resp.Body.Close(); err != nil {
log.Println("ERROR", errors.Wrap(err, "DownloadFile.BodyClose"))
}
}()
out, err := os.Create(filepath)
defer func() {
if err = out.Close(); err != nil {
log.Println("ERROR", errors.Wrap(err, "DownloadFile.OutFileClose"))
}
}()
if err != nil {
return errors.Wrap(err, "DownloadFile.OsCreate")
}
_, err = io.Copy(out, resp.Body)
if err != nil {
return errors.Wrap(err, "DownloadFile.IoCopy")
}
return nil
}
func (c *Client) DownloadFileBytes(fileID string) ([]byte, error) {
file, err := c.Service.Files.Get(fileID).Do()
if err != nil {
return nil, errors.Wrap(err, "DownloadFileBytes.ServiceFilesGetDo")
}
var resp *http.Response
if file.MimeType == MimeTypeGoogle {
resp, err = c.Service.Files.Export(fileID, MimeTypeDocx).Fields("exportFormat", "docx").Download()
err = errors.Wrap(err, "DownloadFileBytes.Export")
defer func() {
if err = resp.Body.Close(); err != nil {
log.Println("ERROR", errors.Wrap(err, "DownloadFileBytes.BodyClose"))
}
}()
} else {
resp, err = c.Service.Files.Get(fileID).Download()
err = errors.Wrap(err, "DownloadFileBytes.Download")
defer func() {
if err = resp.Body.Close(); err != nil {
log.Println("ERROR", errors.Wrap(err, "DownloadFileBytes.BodyClose"))
}
}()
}
if err != nil {
return nil, err
}
defer func() {
if err = resp.Body.Close(); err != nil {
log.Println("ERROR", errors.Wrap(err, "DownloadFile.BodyClose"))
}
}()
return io.ReadAll(resp.Body)
}
// MakeDefaultDirs - проверяет диск на наличие папок DefaultDir, TemplateDir и SaveDir.
// Если папки не существуют, то создает их.
func (c *Client) MakeDefaultDirs(defaultID, defaultName, templateID, templateName, saveID,
saveName string) (*drive.File, *drive.File, *drive.File, error) {
var defaultDir, templateDir, saveDir *drive.File
if defaultName == "" {
defaultName = DefaultDir
}
if templateName == "" {
templateName = TemplateDir
}
if saveName == "" {
saveName = SaveDir
}
var err error
// Check Default directory
if defaultID == "" {
var fl *drive.FileList
fl, err = c.GetResourcesByName(defaultName, "")
if err != nil {
return nil, nil, nil, errors.Wrap(err, "MakeDefaultDirs.DefaultDir.GetResourceByName")
}
if len(fl.Files) == 0 {
defaultDir, err = c.PutResources(defaultName, "")
if err != nil {
return nil, nil, nil, errors.Wrap(err, "MakeDefaultDirs.DefaultDir.PutResource")
}
} else {
defaultDir = fl.Files[0]
}
} else {
defaultDir, err = c.Service.Files.Get(defaultID).Do()
if err != nil {
if strings.Contains(err.Error(), "404") {
defaultDir, err = c.PutResources(defaultName, "")
if err != nil {
return nil, nil, nil, errors.Wrap(err, "MakeDefaultDirs.DefaultDir.PutResource")
}
} else {
return nil, nil, nil, errors.Wrap(err, "MakeDefaultDirs.DefaultDir.ServiceFilesGetDo")
}
}
}
// Check Template Directory
if templateID == "" {
var fl *drive.FileList
fl, err = c.GetResourcesByName(templateName, defaultDir.Id)
if err != nil {
return nil, nil, nil, errors.Wrap(err, "MakeDefaultDirs.TemplateDir.GetResourcesByName")
}
if len(fl.Files) == 0 {
templateDir, err = c.PutResources(templateName, defaultDir.Id)
if err != nil {
return nil, nil, nil, errors.Wrap(err, "MakeDefaultDirs.TemplateDir.PutResources")
}
} else {
templateDir = fl.Files[0]
}
} else {
templateDir, err = c.Service.Files.Get(templateID).Do()
if err != nil {
if strings.Contains(err.Error(), "404") {
templateDir, err = c.PutResources(templateName, defaultDir.Id)
if err != nil {
return nil, nil, nil, errors.Wrap(err, "MakeDefaultDirs.TemplateDir.PutResources")
}
} else {
return nil, nil, nil, errors.Wrap(err, "MakeDefaultDirs.TemplateDir.ServiceFilesGetDo")
}
}
}
// Check Save Directory
if saveID == "" {
var fl *drive.FileList
fl, err = c.GetResourcesByName(saveName, defaultDir.Id)
if err != nil {
return nil, nil, nil, errors.Wrap(err, "MakeDefaultDirs.SaveDir.GetResourcesByName")
}
if len(fl.Files) == 0 {
saveDir, err = c.PutResources(saveName, defaultDir.Id)
if err != nil {
return nil, nil, nil, errors.Wrap(err, "MakeDefaultDirs.SaveDir.PutResources")
}
} else {
saveDir = fl.Files[0]
}
} else {
saveDir, err = c.Service.Files.Get(templateID).Do()
if err != nil {
if strings.Contains(err.Error(), "404") {
saveDir, err = c.PutResources(saveName, defaultDir.Id)
if err != nil {
return nil, nil, nil, errors.Wrap(err, "MakeDefaultDirs.SaveDir.PutResources")
}
} else {
return nil, nil, nil, errors.Wrap(err, "MakeDefaultDirs.SaveDir.ServiceFilesGetDo")
}
}
}
return defaultDir, templateDir, saveDir, nil
}