mirror of
https://github.com/larksuite/cli.git
synced 2026-07-09 02:14:02 +08:00
feat: support user identity for im +chat-create (#242)
- Add --as user support to +chat-create - Add UserScopes (im:chat:create_by_user) / BotScopes (im:chat:create) - Update skill docs and reference files to reflect user/bot support - Default identity remains bot (first element of AuthTypes) Change-Id: I6be0a160567a0d87a92f176ae12297a11d06dcb1
This commit is contained in:
@@ -22,3 +22,8 @@ func TestNewRuntimeContext(cmd *cobra.Command, cfg *core.CliConfig) *RuntimeCont
|
||||
func TestNewRuntimeContextWithCtx(ctx context.Context, cmd *cobra.Command, cfg *core.CliConfig) *RuntimeContext {
|
||||
return &RuntimeContext{ctx: ctx, Cmd: cmd, Config: cfg}
|
||||
}
|
||||
|
||||
// TestNewRuntimeContextWithIdentity creates a RuntimeContext with a specific identity for testing.
|
||||
func TestNewRuntimeContextWithIdentity(cmd *cobra.Command, cfg *core.CliConfig, as core.Identity) *RuntimeContext {
|
||||
return &RuntimeContext{Cmd: cmd, Config: cfg, resolvedAs: as}
|
||||
}
|
||||
|
||||
@@ -531,14 +531,18 @@ func TestMessagesSearchPaginationConfig(t *testing.T) {
|
||||
|
||||
func TestShortcutDryRunShapes(t *testing.T) {
|
||||
t.Run("ImChatCreate dry run includes params and body", func(t *testing.T) {
|
||||
runtime := newTestRuntimeContext(t, map[string]string{
|
||||
"type": "public",
|
||||
"name": "Team Room",
|
||||
"users": "ou_1,ou_2",
|
||||
"owner": "ou_owner",
|
||||
}, map[string]bool{
|
||||
"set-bot-manager": true,
|
||||
})
|
||||
cmd := &cobra.Command{Use: "test"}
|
||||
for _, name := range []string{"type", "name", "users", "owner"} {
|
||||
cmd.Flags().String(name, "", "")
|
||||
}
|
||||
cmd.Flags().Bool("set-bot-manager", false, "")
|
||||
_ = cmd.ParseFlags(nil)
|
||||
_ = cmd.Flags().Set("type", "public")
|
||||
_ = cmd.Flags().Set("name", "Team Room")
|
||||
_ = cmd.Flags().Set("users", "ou_1,ou_2")
|
||||
_ = cmd.Flags().Set("owner", "ou_owner")
|
||||
_ = cmd.Flags().Set("set-bot-manager", "true")
|
||||
runtime := common.TestNewRuntimeContextWithIdentity(cmd, nil, "bot")
|
||||
got := mustMarshalDryRun(t, ImChatCreate.DryRun(context.Background(), runtime))
|
||||
if !strings.Contains(got, `"/open-apis/im/v1/chats"`) || !strings.Contains(got, `"set_bot_manager":true`) || !strings.Contains(got, `"chat_type":"public"`) {
|
||||
t.Fatalf("ImChatCreate.DryRun() = %s", got)
|
||||
|
||||
@@ -19,24 +19,25 @@ import (
|
||||
var ImChatCreate = common.Shortcut{
|
||||
Service: "im",
|
||||
Command: "+chat-create",
|
||||
Description: "Create a group chat with bot identity; bot-only; creates private/public chats, invites users/bots, optionally sets bot manager",
|
||||
Description: "Create a group chat; user/bot; creates private/public chats, invites users/bots, optionally sets bot manager",
|
||||
Risk: "write",
|
||||
Scopes: []string{"im:chat:create"},
|
||||
AuthTypes: []string{"bot"},
|
||||
UserScopes: []string{"im:chat:create_by_user"},
|
||||
BotScopes: []string{"im:chat:create"},
|
||||
AuthTypes: []string{"bot", "user"},
|
||||
HasFormat: true,
|
||||
Flags: []common.Flag{
|
||||
{Name: "name", Desc: "group name (required for public groups, max 60 chars)"},
|
||||
{Name: "description", Desc: "group description (max 100 chars)"},
|
||||
{Name: "users", Desc: "comma-separated user open_ids (ou_xxx) to invite, max 50"},
|
||||
{Name: "bots", Desc: "comma-separated bot app IDs (cli_xxx) to invite, max 5"},
|
||||
{Name: "owner", Desc: "owner open_id (ou_xxx); defaults to the bot if not specified"},
|
||||
{Name: "owner", Desc: "owner open_id (ou_xxx); defaults to bot (--as bot) or authorized user (--as user)"},
|
||||
{Name: "type", Default: "private", Desc: "chat type", Enum: []string{"private", "public"}},
|
||||
{Name: "set-bot-manager", Type: "bool", Desc: "set the bot that creates this chat as manager"},
|
||||
{Name: "set-bot-manager", Type: "bool", Desc: "set the bot that creates this chat as manager (bot identity only)"},
|
||||
},
|
||||
DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI {
|
||||
body := buildCreateChatBody(runtime)
|
||||
params := map[string]interface{}{"user_id_type": "open_id"}
|
||||
if runtime.Bool("set-bot-manager") {
|
||||
if runtime.Bool("set-bot-manager") && runtime.IsBot() {
|
||||
params["set_bot_manager"] = true
|
||||
}
|
||||
return common.NewDryRunAPI().
|
||||
@@ -45,6 +46,10 @@ var ImChatCreate = common.Shortcut{
|
||||
Body(body)
|
||||
},
|
||||
Validate: func(ctx context.Context, runtime *common.RuntimeContext) error {
|
||||
if runtime.Bool("set-bot-manager") && !runtime.IsBot() {
|
||||
return output.ErrValidation("--set-bot-manager is only supported with bot identity (--as bot)")
|
||||
}
|
||||
|
||||
name := runtime.Str("name")
|
||||
chatType := runtime.Str("type")
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ Shortcut 是对常用操作的高级封装(`lark-cli im +<verb> [flags]`)。
|
||||
|
||||
| Shortcut | 说明 |
|
||||
|----------|------|
|
||||
| [`+chat-create`](references/lark-im-chat-create.md) | Create a group chat with bot identity; bot-only; creates private/public chats, invites users/bots, optionally sets bot manager |
|
||||
| [`+chat-create`](references/lark-im-chat-create.md) | Create a group chat; user/bot; creates private/public chats, invites users/bots, optionally sets bot manager |
|
||||
| [`+chat-messages-list`](references/lark-im-chat-messages-list.md) | List messages in a chat or P2P conversation; user/bot; accepts --chat-id or --user-id, resolves P2P chat_id, supports time range/sort/pagination |
|
||||
| [`+chat-search`](references/lark-im-chat-search.md) | Search visible group chats by keyword and/or member open_ids (e.g. look up chat_id by group name); user/bot; supports member/type filters, sorting, and pagination |
|
||||
| [`+chat-update`](references/lark-im-chat-update.md) | Update group chat name or description; user/bot; updates a chat's name or description |
|
||||
|
||||
@@ -2,10 +2,13 @@
|
||||
|
||||
> **Prerequisite:** Read [`../lark-shared/SKILL.md`](../../lark-shared/SKILL.md) first to understand authentication, global parameters, and safety rules.
|
||||
|
||||
Create a group chat using **bot identity (TAT)**. You can specify the group name, description, members (users/bots), owner, and chat type (private/public).
|
||||
Create a group chat. Supports both user identity (`--as user`) and bot identity (`--as bot`). You can specify the group name, description, members (users/bots), owner, and chat type (private/public).
|
||||
|
||||
This skill maps to the shortcut: `lark-cli im +chat-create` (internally calls `POST /open-apis/im/v1/chats`).
|
||||
|
||||
- `--as bot` requires the `im:chat:create` scope.
|
||||
- `--as user` requires the `im:chat:create_by_user` scope.
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
@@ -27,12 +30,18 @@ lark-cli im +chat-create --name "My Group" --bots "cli_aaa,cli_bbb"
|
||||
# Invite both users and bots
|
||||
lark-cli im +chat-create --name "My Group" --users "ou_aaa" --bots "cli_aaa"
|
||||
|
||||
# Make the creating bot a group manager
|
||||
lark-cli im +chat-create --name "My Group" --set-bot-manager
|
||||
# Make the creating bot a group manager (bot identity only)
|
||||
lark-cli im +chat-create --name "My Group" --set-bot-manager --as bot
|
||||
|
||||
# JSON output
|
||||
lark-cli im +chat-create --name "My Group" --format json
|
||||
|
||||
# Create a group with bot identity
|
||||
lark-cli im +chat-create --name "My Group" --users "ou_aaa" --as bot
|
||||
|
||||
# Create a group with user identity
|
||||
lark-cli im +chat-create --name "My Group" --users "ou_aaa,ou_bbb" --as user
|
||||
|
||||
# Preview the request without creating anything
|
||||
lark-cli im +chat-create --name "My Group" --dry-run
|
||||
```
|
||||
@@ -45,24 +54,25 @@ lark-cli im +chat-create --name "My Group" --dry-run
|
||||
| `--description <text>` | No | Max 100 characters | Group description |
|
||||
| `--users <ids>` | No | Up to 50, format `ou_xxx` | Comma-separated user open_ids |
|
||||
| `--bots <ids>` | No | Up to 5, format `cli_xxx` | Comma-separated bot app IDs |
|
||||
| `--owner <open_id>` | No | Format `ou_xxx` | Owner open_id (defaults to the bot if not specified) |
|
||||
| `--owner <open_id>` | No | Format `ou_xxx` | Owner open_id (defaults to the bot when using `--as bot`, or the authorized user when using `--as user`) |
|
||||
| `--type <type>` | No | `private` (default) or `public` | Group type |
|
||||
| `--set-bot-manager` | No | - | Set the creating bot as a group manager |
|
||||
| `--set-bot-manager` | No | - | Set the creating bot as a group manager (only effective with `--as bot`) |
|
||||
| `--format json` | No | - | Output as JSON |
|
||||
| `--as <identity>` | No | `bot` or `user` | Identity type |
|
||||
| `--dry-run` | No | - | Preview the request without executing it |
|
||||
|
||||
> **Note:** Only bot identity is supported.
|
||||
|
||||
## AI Usage Guidance
|
||||
|
||||
When the user asks to create a group, always use the **two-step flow** below. Do NOT pass other users' open_ids in `--users` during group creation — the bot and target users are often mutually invisible (error 232043).
|
||||
### When using `--as bot`
|
||||
|
||||
1. **Get the current user's open_id:** Run `lark-cli contact +get-user` to retrieve it.
|
||||
Bot may fail to invite users who are mutually invisible to it during group creation (error 232043). To avoid this, use the **two-step flow** below instead of passing other users' open_ids in `--users`.
|
||||
|
||||
1. **Get the current user's open_id:** Run `lark-cli contact +search-user --query "<name or email>"` to retrieve it.
|
||||
2. **Create the group — by default include the current user:**
|
||||
|
||||
```bash
|
||||
lark-cli im +chat-create --name "<group name>" \
|
||||
--users "<current user open_id>"
|
||||
--users "<current user open_id>" --as bot
|
||||
```
|
||||
|
||||
**Default behavior:** Always add the current user to the group, unless the user explicitly says "do not add me" or "bot-only group" — only then omit `--users`.
|
||||
@@ -80,6 +90,16 @@ When the user asks to create a group, always use the **two-step flow** below. Do
|
||||
|
||||
4. **Check `invalid_id_list`** in the response. If non-empty, report to the user which members could not be added.
|
||||
|
||||
### When using `--as user`
|
||||
|
||||
User identity does not have the bot visibility limitation, so you can create the group and invite members in one step:
|
||||
|
||||
```bash
|
||||
lark-cli im +chat-create --name "<group name>" --users "ou_aaa,ou_bbb" --as user
|
||||
```
|
||||
|
||||
The authorized user is automatically the group creator and member.
|
||||
|
||||
## Output Fields
|
||||
|
||||
| Field | Description |
|
||||
@@ -119,7 +139,7 @@ lark-cli im +messages-send --chat-id "$CHAT_ID" --text "Welcome, everyone!"
|
||||
|
||||
| Symptom | Root Cause | Solution |
|
||||
|---------|---------|---------|
|
||||
| Permission denied (99991672) | The bot app does not have `im:chat:create` TAT permission enabled | Enable the required permission for the app in the Open Platform console |
|
||||
| Permission denied (99991672) | The app does not have `im:chat:create` (bot) or `im:chat:create_by_user` (user) permission enabled | Enable the required permission for the app in the Open Platform console |
|
||||
| `--name is required for public groups and must be at least 2 characters` | A public group was created without a name or with a name shorter than 2 characters | Provide a name with at least 2 characters |
|
||||
| `--name exceeds the maximum of 60 characters` | The group name is too long | Shorten the name to 60 characters or fewer |
|
||||
| `--description exceeds the maximum of 100 characters` | The group description is too long | Shorten the description to 100 characters or fewer |
|
||||
|
||||
@@ -13,7 +13,7 @@ Group-chat operations support both `--as user` (UAT user identity) and `--as bot
|
||||
|
||||
| Operation | Recommended Identity | Why |
|
||||
|------|---------|-----------------------------------|
|
||||
| Create group (`+chat-create`) | Depends on the scenario | Default is bot |
|
||||
| Create group (`+chat-create`) | Depends on the scenario | Infer from context |
|
||||
| Add members (member-management flow) | `--as user` | Bot visibility is limited and often fails when the target user is mutually invisible to the bot (232024) |
|
||||
| Update group (`+chat-update`) | Owner identity | Permission changes require owner/admin privileges; owner transfer requires owner identity |
|
||||
|
||||
|
||||
Reference in New Issue
Block a user