Files
larksuite--cli/shortcuts/im/im_feed_shortcut_create.go
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

98 lines
3.1 KiB
Go

// Copyright (c) 2026 Lark Technologies Pte. Ltd.
// SPDX-License-Identifier: MIT
package im
import (
"context"
"github.com/larksuite/cli/errs"
"github.com/larksuite/cli/shortcuts/common"
)
// ImFeedShortcutCreate provides the +feed-shortcut-create shortcut for adding
// chats to the user's feed shortcuts. Currently only CHAT-type shortcuts are
// exposed by the OpenAPI gateway; feed_card_id must be an open_chat_id
// (oc_xxx).
var ImFeedShortcutCreate = common.Shortcut{
Service: "im",
Command: "+feed-shortcut-create",
Description: "Add chats to the user's feed shortcuts; user-only; batch up to 10 chat IDs per call; --head/--tail controls insertion order",
Risk: "write",
UserScopes: []string{feedShortcutWriteScope},
AuthTypes: []string{"user"},
HasFormat: true,
Flags: []common.Flag{
// chat-id is mandatory but intentionally not cobra-Required: the
// requiredness check lives in collectChatIDs so a missing flag is
// reported through the structured validation envelope (exit 2)
// instead of cobra's plain-text error.
{Name: "chat-id", Type: "string_slice",
Desc: "open_chat_id to add as a feed shortcut (oc_xxx); required; repeat the flag or pass comma-separated; max 10 per call"},
{Name: "head", Type: "bool",
Desc: "insert at the top of the shortcut list (default); mutually exclusive with --tail"},
{Name: "tail", Type: "bool",
Desc: "append at the bottom of the shortcut list; mutually exclusive with --head"},
},
Validate: func(ctx context.Context, runtime *common.RuntimeContext) error {
if _, err := collectChatIDs(runtime); err != nil {
return err
}
_, err := resolveIsHeader(runtime)
return err
},
DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI {
ids, err := collectChatIDs(runtime)
if err != nil {
return common.NewDryRunAPI().Set("error", err.Error())
}
isHeader, err := resolveIsHeader(runtime)
if err != nil {
return common.NewDryRunAPI().Set("error", err.Error())
}
return common.NewDryRunAPI().
POST("/open-apis/im/v2/feed_shortcuts").
Body(map[string]any{
"shortcuts": buildShortcutItems(ids),
"is_header": isHeader,
})
},
Execute: func(ctx context.Context, runtime *common.RuntimeContext) error {
ids, err := collectChatIDs(runtime)
if err != nil {
return err
}
isHeader, err := resolveIsHeader(runtime)
if err != nil {
return err
}
items := buildShortcutItems(ids)
data, err := runtime.DoAPIJSONTyped("POST", "/open-apis/im/v2/feed_shortcuts", nil,
map[string]any{
"shortcuts": items,
"is_header": isHeader,
})
if err != nil {
return err
}
return emitFeedShortcutWriteResult(runtime, items, data)
},
}
// resolveIsHeader determines the insertion position.
// - default (neither flag set) → true (head)
// - --head → true
// - --tail → false
// - both set → error
func resolveIsHeader(rt *common.RuntimeContext) (bool, error) {
head := rt.Bool("head")
tail := rt.Bool("tail")
if head && tail {
return false, errs.NewValidationError(errs.SubtypeInvalidArgument, "--head and --tail are mutually exclusive")
}
if tail {
return false, nil
}
return true, nil
}