contact

package
v1.0.21 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 28, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ContactGetUser = common.Shortcut{
	Service:     "contact",
	Command:     "+get-user",
	Description: "Get user info (omit user_id for self; provide user_id for specific user)",
	Risk:        "read",
	UserScopes:  []string{"contact:user.basic_profile:readonly"},
	BotScopes:   []string{"contact:user.base:readonly", "contact:contact.base:readonly"},
	AuthTypes:   []string{"user", "bot"},
	HasFormat:   true,
	Flags: []common.Flag{
		{Name: "user-id", Desc: "user ID (omit to get current user)"},
		{Name: "user-id-type", Default: "open_id", Desc: "user ID type: open_id | union_id | user_id"},
	},
	Validate: func(ctx context.Context, runtime *common.RuntimeContext) error {
		if runtime.Str("user-id") == "" && runtime.IsBot() {
			return common.FlagErrorf("bot identity cannot get current user info, specify --user-id")
		}
		return nil
	},
	DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI {
		userId := runtime.Str("user-id")
		if userId == "" {
			return common.NewDryRunAPI().
				GET("/open-apis/authen/v1/user_info").
				Desc("(when --user-id omitted) Get current authenticated user info").
				Set("mode", "current_user")
		}
		userIdType := runtime.Str("user-id-type")
		if userIdType == "" {
			userIdType = "open_id"
		}
		if runtime.IsBot() {
			return common.NewDryRunAPI().
				GET("/open-apis/contact/v3/users/:user_id").
				Desc("(bot) Get user info by user ID").
				Params(map[string]interface{}{"user_id_type": userIdType}).
				Set("user_id", userId).Set("user_id_type", userIdType)
		}
		return common.NewDryRunAPI().
			POST("/open-apis/contact/v3/users/basic_batch").
			Desc("(user) Get user basic info by user ID").
			Params(map[string]interface{}{"user_id_type": userIdType}).
			Body(map[string]interface{}{"user_ids": []string{userId}})
	},
	Execute: func(ctx context.Context, runtime *common.RuntimeContext) error {
		userId := runtime.Str("user-id")
		userIdType := runtime.Str("user-id-type")

		if userId == "" {

			data, err := runtime.CallAPI("GET", "/open-apis/authen/v1/user_info", nil, nil)
			if err != nil {
				return err
			}
			user := data
			if user == nil {
				user = make(map[string]interface{})
			}
			userData := map[string]interface{}{"user": user}
			runtime.OutFormat(userData, nil, func(w io.Writer) {
				output.PrintTable(w, []map[string]interface{}{{
					"name":             pickUserName(user),
					"open_id":          user["open_id"],
					"union_id":         user["union_id"],
					"email":            firstNonEmpty(user, "email", "mail"),
					"mobile":           firstNonEmpty(user, "mobile", "phone"),
					"enterprise_email": firstNonEmpty(user, "enterprise_email"),
				}})
			})
			return nil
		}

		if runtime.IsBot() {

			data, err := runtime.CallAPI("GET", "/open-apis/contact/v3/users/"+url.PathEscape(userId),
				map[string]interface{}{"user_id_type": userIdType}, nil)
			if err != nil {
				return err
			}
			user, _ := data["user"].(map[string]interface{})
			if user == nil {
				user = data
			}
			userData := map[string]interface{}{"user": user}
			runtime.OutFormat(userData, nil, func(w io.Writer) {
				output.PrintTable(w, []map[string]interface{}{{
					"name":       pickUserName(user),
					"open_id":    firstNonEmpty(user, "open_id", "user_id"),
					"email":      firstNonEmpty(user, "email", "enterprise_email"),
					"mobile":     firstNonEmpty(user, "mobile", "mobile_phone"),
					"department": firstNonEmpty(user, "department_name"),
				}})
			})
			return nil
		}

		data, err := runtime.CallAPI("POST", "/open-apis/contact/v3/users/basic_batch",
			map[string]interface{}{"user_id_type": userIdType},
			map[string]interface{}{"user_ids": []string{userId}})
		if err != nil {
			return err
		}
		users, _ := data["users"].([]interface{})
		var user map[string]interface{}
		if len(users) > 0 {
			user, _ = users[0].(map[string]interface{})
		}
		if user == nil {
			user = make(map[string]interface{})
		}
		userData := map[string]interface{}{"user": user}
		runtime.OutFormat(userData, nil, func(w io.Writer) {
			output.PrintTable(w, []map[string]interface{}{{
				"name":    pickUserName(user),
				"user_id": user["user_id"],
			}})
		})
		return nil
	},
}
View Source
var ContactSearchUser = common.Shortcut{
	Service:     "contact",
	Command:     "+search-user",
	Description: "Search Lark/Feishu users by keyword, open_id list, or filter (requires --as user)",
	Risk:        "read",
	Scopes:      []string{"contact:user:search"},
	AuthTypes:   []string{"user"},
	HasFormat:   true,
	Flags: []common.Flag{
		{Name: "query", Desc: "search keyword (≤ 50 characters)"},
		{Name: "user-ids", Desc: "open_ids to look up or restrict --query against (CSV; me = caller; ≤ 100)"},
		{Name: "has-chatted", Type: "bool", Desc: "restrict to users you've chatted with (omit to disable; =false rejected)"},
		{Name: "has-enterprise-email", Type: "bool", Desc: "restrict to users with enterprise email (omit to disable; =false rejected)"},
		{Name: "exclude-external-users", Type: "bool", Desc: "exclude external (cross-tenant) users; default includes them (omit to disable; =false rejected)"},
		{Name: "left-organization", Type: "bool", Desc: "restrict to users who have left the organization (omit to disable; =false rejected)"},
		{Name: "lang", Desc: "override locale for localized_name (e.g. zh_cn, en_us)"},
		{Name: "page-size", Type: "int", Default: "20", Desc: "rows per request, 1-30"},
	},
	Tips: []string{
		"Keyword search: lark-cli contact +search-user --query 'alice' --format json",
		"Look up by ID (or 'me' for self): lark-cli contact +search-user --user-ids 'ou_xxx,me' --format json",
		"Filter-only enumeration — users you've chatted with: lark-cli contact +search-user --has-chatted --format json",
		"Refine same-name hits: lark-cli contact +search-user --query '张三' --has-chatted --exclude-external-users",
		"open_id is the stable identifier for follow-up commands; on has_more=true add filters or tighten --query — there is no auto-pagination.",
	},
	Validate: func(ctx context.Context, runtime *common.RuntimeContext) error {
		return validateSearchUser(runtime)
	},
	DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI {
		body, err := buildSearchUserBody(runtime)
		if err != nil {
			return common.NewDryRunAPI().Set("error", err.Error())
		}
		return common.NewDryRunAPI().
			POST(searchUserURL).
			Params(map[string]interface{}{"page_size": runtime.Int("page-size")}).
			Body(body)
	},
	Execute: executeSearchUser,
}

Functions

func Shortcuts

func Shortcuts() []common.Shortcut

Shortcuts returns all contact shortcuts.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL