Files
wehub-resource-sync bf9395e022
CI / license-header (push) Has been skipped
CI / e2e-dry-run (push) Has been skipped
CI / fast-gate (push) Failing after 0s
Test PR Label Logic / test-pr-labels (push) Failing after 1s
Skill Format Check / check-format (push) Failing after 2s
CI / security (push) Failing after 5s
CI / unit-test (push) Has been skipped
CI / lint (push) Has been skipped
CI / script-test (push) Has been skipped
CI / deterministic-gate (push) Has been skipped
CI / coverage (push) Has been skipped
CI / results (push) Has been cancelled
CI / deadcode (push) Has been cancelled
CI / e2e-live (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:22:54 +08:00

137 lines
4.6 KiB
Go

// Copyright (c) 2026 Lark Technologies Pte. Ltd.
// SPDX-License-Identifier: MIT
package drive
import (
"context"
"fmt"
"strings"
"github.com/larksuite/cli/errs"
"github.com/larksuite/cli/internal/validate"
"github.com/larksuite/cli/shortcuts/common"
)
var driveCreateShortcutAllowedTypes = map[string]bool{
"file": true,
"docx": true,
"bitable": true,
"doc": true,
"sheet": true,
"mindnote": true,
"slides": true,
}
type driveCreateShortcutSpec struct {
FileToken string
FileType string
FolderToken string
}
func newDriveCreateShortcutSpec(runtime *common.RuntimeContext) driveCreateShortcutSpec {
return driveCreateShortcutSpec{
FileToken: strings.TrimSpace(runtime.Str("file-token")),
FileType: strings.ToLower(strings.TrimSpace(runtime.Str("type"))),
FolderToken: strings.TrimSpace(runtime.Str("folder-token")),
}
}
// RequestBody builds the create_shortcut API payload from the shortcut spec.
func (s driveCreateShortcutSpec) RequestBody() map[string]interface{} {
return map[string]interface{}{
"parent_token": s.FolderToken,
"refer_entity": map[string]interface{}{
"refer_token": s.FileToken,
"refer_type": s.FileType,
},
}
}
// DriveCreateShortcut creates a Drive shortcut for an existing file in another folder.
var DriveCreateShortcut = common.Shortcut{
Service: "drive",
Command: "+create-shortcut",
Description: "Create a Drive shortcut in another folder",
Risk: "write",
Scopes: []string{"space:document:shortcut"},
AuthTypes: []string{"user", "bot"},
Flags: []common.Flag{
{Name: "file-token", Desc: "source file token to reference", Required: true},
{Name: "type", Desc: "source file type (file, docx, bitable, doc, sheet, mindnote, slides)", Required: true},
{Name: "folder-token", Desc: "target folder token for the new shortcut", Required: true},
},
Validate: func(ctx context.Context, runtime *common.RuntimeContext) error {
return validateDriveCreateShortcutSpec(newDriveCreateShortcutSpec(runtime))
},
DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI {
spec := newDriveCreateShortcutSpec(runtime)
return common.NewDryRunAPI().
Desc("Create a Drive shortcut").
POST("/open-apis/drive/v1/files/create_shortcut").
Desc("[1] Create shortcut").
Body(spec.RequestBody())
},
Execute: func(ctx context.Context, runtime *common.RuntimeContext) error {
spec := newDriveCreateShortcutSpec(runtime)
fmt.Fprintf(
runtime.IO().ErrOut,
"Creating shortcut for %s %s in folder %s...\n",
spec.FileType,
common.MaskToken(spec.FileToken),
common.MaskToken(spec.FolderToken),
)
data, err := runtime.CallAPITyped(
"POST",
"/open-apis/drive/v1/files/create_shortcut",
nil,
spec.RequestBody(),
)
if err != nil {
return err
}
out := map[string]interface{}{
"created": true,
"source_file_token": spec.FileToken,
"source_type": spec.FileType,
"folder_token": spec.FolderToken,
}
if shortcutToken := common.GetString(data, "succ_shortcut_node", "token"); shortcutToken != "" {
out["shortcut_token"] = shortcutToken
}
if url := common.GetString(data, "succ_shortcut_node", "url"); url != "" {
out["url"] = url
}
if title := common.GetString(data, "succ_shortcut_node", "name"); title != "" {
out["title"] = title
}
runtime.Out(out, nil)
return nil
},
}
// validateDriveCreateShortcutSpec validates shortcut creation inputs before API execution.
func validateDriveCreateShortcutSpec(spec driveCreateShortcutSpec) error {
if err := validate.ResourceName(spec.FileToken, "--file-token"); err != nil {
return errs.NewValidationError(errs.SubtypeInvalidArgument, "%s", err).WithParam("--file-token")
}
if err := validate.ResourceName(spec.FolderToken, "--folder-token"); err != nil {
return errs.NewValidationError(errs.SubtypeInvalidArgument, "%s", err).WithParam("--folder-token")
}
if spec.FileType == "wiki" {
return errs.NewValidationError(errs.SubtypeInvalidArgument, "unsupported file type: wiki. This shortcut only supports Drive file tokens; wiki documents must be resolved to their underlying file token first").WithParam("--type")
}
if spec.FileType == "folder" {
return errs.NewValidationError(errs.SubtypeInvalidArgument, "unsupported file type: folder. The create_shortcut API only supports Drive files, not folders").WithParam("--type")
}
if !driveCreateShortcutAllowedTypes[spec.FileType] {
return errs.NewValidationError(errs.SubtypeInvalidArgument, "unsupported file type: %s. Supported types: file, docx, bitable, doc, sheet, mindnote, slides", spec.FileType).WithParam("--type")
}
return nil
}