gogcli/internal/cmd/export_via_drive.go
2026-04-28 02:26:43 +01:00

124 lines
2.9 KiB
Go

package cmd
import (
"context"
"errors"
"fmt"
"os"
"strings"
"github.com/steipete/gogcli/internal/config"
"github.com/steipete/gogcli/internal/outfmt"
"github.com/steipete/gogcli/internal/ui"
)
type exportViaDriveOptions struct {
Op string
ArgName string
ExpectedMime string
KindLabel string
DefaultFormat string
FormatHelp string
}
const defaultExportFormat = "pdf"
func exportViaDrive(ctx context.Context, flags *RootFlags, opts exportViaDriveOptions, id string, outPathFlag string, format string) error {
u := ui.FromContext(ctx)
argName := strings.TrimSpace(opts.ArgName)
if argName == "" {
argName = "id"
}
id = normalizeGoogleID(strings.TrimSpace(id))
if id == "" {
return usage(fmt.Sprintf("empty %s", argName))
}
// Avoid touching auth/keyring and avoid writing files in dry-run mode.
outPathFlag = strings.TrimSpace(outPathFlag)
if outPathFlag != "" {
expanded, err := config.ExpandPath(outPathFlag)
if err != nil {
return err
}
outPathFlag = expanded
}
format = strings.TrimSpace(format)
if format == "" {
format = strings.TrimSpace(opts.DefaultFormat)
}
if format == "" {
format = defaultExportFormat
}
op := strings.TrimSpace(opts.Op)
if op == "" {
op = "drive.export"
}
var defaultDownloadsDir string
if outPathFlag == "" {
if dir, err := config.DriveDownloadsDir(); err == nil {
defaultDownloadsDir = dir
}
}
if err := dryRunExit(ctx, flags, op, map[string]any{
"id": id,
"out": outPathFlag,
"default_downloads_dir": defaultDownloadsDir,
"format": format,
"expected_mime": strings.TrimSpace(opts.ExpectedMime),
"kind": strings.TrimSpace(opts.KindLabel),
}); err != nil {
return err
}
_, svc, err := requireDriveService(ctx, flags)
if err != nil {
return err
}
meta, err := svc.Files.Get(id).
SupportsAllDrives(true).
Fields("id, name, mimeType").
Context(ctx).
Do()
if err != nil {
return err
}
if meta == nil {
return errors.New("file not found")
}
if opts.ExpectedMime != "" && meta.MimeType != opts.ExpectedMime {
label := strings.TrimSpace(opts.KindLabel)
if label == "" {
label = "expected type"
}
return fmt.Errorf("file is not a %s (mimeType=%q)", label, meta.MimeType)
}
destPath, err := resolveDriveDownloadDestPath(meta, outPathFlag)
if err != nil {
return err
}
if outfmt.IsJSON(ctx) && isStdoutPath(destPath) {
return usage("can't combine --json with --out -")
}
downloadedPath, size, err := downloadDriveFile(ctx, svc, meta, destPath, format)
if err != nil {
return err
}
if outfmt.IsJSON(ctx) {
return outfmt.WriteJSON(ctx, os.Stdout, map[string]any{"path": downloadedPath, "size": size})
}
if isStdoutPath(downloadedPath) {
return nil
}
u.Out().Printf("path\t%s", downloadedPath)
u.Out().Printf("size\t%s", formatDriveSize(size))
return nil
}