package GDisk import ( "context" "errors" "fmt" "golang.org/x/oauth2" "golang.org/x/oauth2/google" "google.golang.org/api/drive/v3" "google.golang.org/api/option" "io" "net/http" "os" "penahub.gitlab.yandexcloud.net/backend/templategen/tools" "strings" ) const ( DefaultDir = "TemplateGenerator" TemplateDir = "templates" SaveDir = "saved" MimeTypeDocx = "application/vnd.openxmlformats-officedocument.wordprocessingml.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, err } config, err := google.ConfigFromJSON(b, drive.DriveScope, drive.DriveMetadataScope, ) if err != nil { return nil, err } return &ClientApp{Config: config}, nil } func (ca *ClientApp) GenerateOAuthUrl(userId, redirectUrl string) (string, error) { state, err := tools.EncryptTokenRC4(tools.StateToken{ UserID: userId, Service: "google", RedirectUrl: redirectUrl, }) if err != nil { return "", err } 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, err } return token, nil } func (ca *ClientApp) NewClient(ctx context.Context, token *oauth2.Token) (*Client, error) { client := ca.Config.Client(ctx, token) srv, err := drive.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return nil, err } return &Client{ App: ca, HTTPClient: client, Service: srv, 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() { srv, err := drive.NewService(context.Background(), option.WithHTTPClient(c.HTTPClient)) if err != nil { fmt.Println("err123", err) return } about, err := srv.About.Get().Fields("storageQuota", "user", "exportFormats", "maxImportSizes", "maxUploadSize").Do() if err != nil { fmt.Println("err1234", err) return } fmt.Printf("srv.About %+v \r\n", about.User) dl, err := srv.Drives.List().Do() if err != nil { fmt.Println("err12345", err) return } fmt.Println("DRIVES ________________________") for _, drive := range dl.Drives { fmt.Println(drive) } } // GetUserInfo - получить информацию о пользователе Google func (c *Client) GetUserInfo() (*drive.User, error) { srv, err := drive.NewService(context.Background(), option.WithHTTPClient(c.HTTPClient)) if err != nil { return nil, err } about, err := srv.About.Get().Fields("user").Do() if err != nil { return nil, err } if about == nil { return nil, errors.New("got empty about") } if about.User == nil { return nil, errors.New("got empty about.User") } 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, err } 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, err } return fl, nil } // PutResources - создание папки func (c *Client) PutResources(name, parentID string) (*drive.File, error) { q := &drive.File{Name: name, MimeType: "application/vnd.google-apps.folder", IsAppAuthorized: true} if parentID != "" { q.Parents = []string{parentID} } f, err := c.Service.Files.Create(q).Do() if err != nil { fmt.Println("3", err.Error()) fmt.Println("") return nil, err } return f, nil } func (c *Client) DeleteResources(id string) error { return c.Service.Files.Delete(id).Do() } // UploadFile - отправить файл в диск func (c *Client) UploadFile(filepath, mimetype, parentID string) (string, string, error) { file, err := os.Open(filepath) defer file.Close() if err != nil { return "", "", err } filename := strings.Split(file.Name(), "/") q := &drive.File{ Name: filename[len(filename)-1], MimeType: mimetype, IsAppAuthorized: true, } if parentID != "" { q.Parents = []string{parentID} } fileData, err := c.Service.Files.Create(q).Media(file).Do() if err != nil { return "", "", err } 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 err } var resp *http.Response fmt.Println("mimeType", file.MimeType) if file.MimeType == "application/vnd.google-apps.document" { resp, err = c.Service.Files.Export(fileID, MimeTypeDocx). Fields("exportFormat", "docx"). Download() } else { resp, err = c.Service.Files.Get(fileID).Download() } if err != nil { return err } defer resp.Body.Close() out, err := os.Create(filepath) defer out.Close() if err != nil { return err } _, err = io.Copy(out, resp.Body) if err != nil { return err } return nil } // 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 == "" { fl, err := c.GetResourcesByName(defaultName, "") if err != nil { return nil, nil, nil, err } if len(fl.Files) == 0 { defaultDir, err = c.PutResources(defaultName, "") if err != nil { return nil, nil, nil, err } } 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, err } } else { return nil, nil, nil, err } } } // Check Template Directory if templateId == "" { fl, err := c.GetResourcesByName(templateName, defaultDir.Id) if err != nil { return nil, nil, nil, err } if len(fl.Files) == 0 { templateDir, err = c.PutResources(templateName, defaultDir.Id) if err != nil { return nil, nil, nil, err } } 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, err } } else { return nil, nil, nil, err } } } // Check Save Directory if saveId == "" { fl, err := c.GetResourcesByName(saveName, defaultDir.Id) if err != nil { return nil, nil, nil, err } if len(fl.Files) == 0 { saveDir, err = c.PutResources(saveName, defaultDir.Id) if err != nil { return nil, nil, nil, err } } 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, err } } else { return nil, nil, nil, err } } } return defaultDir, templateDir, saveDir, nil }