gogcli/internal/cmd/open.go
salmonumbrella 3371e3f3ad
feat(cli): agent ergonomics + gmail watch exclude labels (#201)
* feat(cli): improve agent ergonomics

* fix(cli): address code review findings

- Fix nil pointer dereference in confirmDestructive when flags is nil
- Deduplicate dry-run logic by delegating to dryRunExit
- Remove deprecated net.Error.Temporary() call (dead since Go 1.18)
- Add unit tests for resolveTasklistID and resolveCalendarID

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: resolve PR #201 conflicts and follow-ups (#201) (thanks @salmonumbrella)

* fix: resolve rebase fallout for PR #201 landing (#201) (thanks @salmonumbrella)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 03:09:49 +01:00

140 lines
3.6 KiB
Go

package cmd
import (
"context"
"fmt"
"os"
"strings"
"github.com/steipete/gogcli/internal/outfmt"
)
type OpenCmd struct {
Target string `arg:"" name:"target" help:"Google URL or ID"`
Type string `name:"type" help:"Type hint (auto|drive|folder|docs|sheets|slides|gmail-thread)" default:"auto" enum:"auto,drive,folder,docs,sheets,slides,gmail-thread"`
}
func (c *OpenCmd) Run(ctx context.Context) error {
// Always emit untransformed JSON, even if the caller enabled global JSON transforms.
ctx = outfmt.WithJSONTransform(ctx, outfmt.JSONTransform{})
target := strings.TrimSpace(c.Target)
if target == "" {
return usage("empty target")
}
kind := strings.ToLower(strings.TrimSpace(c.Type))
if kind == "" {
kind = colorAuto
}
url := bestEffortWebURL(kind, target)
if strings.TrimSpace(url) == "" {
url = target
}
if outfmt.IsJSON(ctx) {
return outfmt.WriteJSON(ctx, os.Stdout, map[string]any{
"input": target,
"type": kind,
"url": url,
})
}
if outfmt.IsPlain(ctx) {
_, _ = fmt.Fprintf(os.Stdout, "type\t%s\n", kind)
_, _ = fmt.Fprintf(os.Stdout, "url\t%s\n", url)
return nil
}
_, _ = fmt.Fprintln(os.Stdout, url)
return nil
}
func bestEffortWebURL(kind string, input string) string {
kind = strings.ToLower(strings.TrimSpace(kind))
input = strings.TrimSpace(input)
if input == "" {
return ""
}
id := normalizeGoogleID(input)
switch kind {
case "drive", colorAuto:
// If it's a known Google URL already, prefer canonicalized forms.
if u := parseMaybeURL(input); u != nil {
host := strings.ToLower(strings.TrimPrefix(strings.TrimSpace(u.Host), "www."))
switch host {
case "drive.google.com":
// Preserve folder URLs when detected.
if strings.Contains(u.Path, "/folders/") {
if id != "" {
return fmt.Sprintf("https://drive.google.com/drive/folders/%s", id)
}
}
// Generic best-effort file open URL.
if id != "" {
return fmt.Sprintf("https://drive.google.com/open?id=%s", id)
}
case "docs.google.com":
// Keep doc-type-specific canonical URLs when possible.
if id == "" {
return input
}
if strings.Contains(u.Path, "/document/") {
return fmt.Sprintf("https://docs.google.com/document/d/%s/edit", id)
}
if strings.Contains(u.Path, "/spreadsheets/") {
return fmt.Sprintf("https://docs.google.com/spreadsheets/d/%s/edit", id)
}
if strings.Contains(u.Path, "/presentation/") {
return fmt.Sprintf("https://docs.google.com/presentation/d/%s/edit", id)
}
return fmt.Sprintf("https://drive.google.com/open?id=%s", id)
case "mail.google.com", "gmail.google.com":
th := normalizeGmailThreadID(input)
if th != "" && th != input {
return fmt.Sprintf("https://mail.google.com/mail/u/0/#all/%s", th)
}
return input
default:
return input
}
}
if id != "" {
return fmt.Sprintf("https://drive.google.com/open?id=%s", id)
}
return input
case "folder":
if id != "" {
return fmt.Sprintf("https://drive.google.com/drive/folders/%s", id)
}
return ""
case "docs":
if id != "" {
return fmt.Sprintf("https://docs.google.com/document/d/%s/edit", id)
}
return ""
case "sheets":
if id != "" {
return fmt.Sprintf("https://docs.google.com/spreadsheets/d/%s/edit", id)
}
return ""
case "slides":
if id != "" {
return fmt.Sprintf("https://docs.google.com/presentation/d/%s/edit", id)
}
return ""
case "gmail-thread":
th := normalizeGmailThreadID(input)
if strings.TrimSpace(th) == "" {
return ""
}
return fmt.Sprintf("https://mail.google.com/mail/u/0/#all/%s", th)
default:
return ""
}
}