mirror of
https://github.com/larksuite/cli.git
synced 2026-09-14 18:42:53 +08:00
fc9f9c1f26
* feat(contact +search-user): add search filters and richer profile fields
- Filter results by chat history, employment status, tenant boundary,
or enterprise email presence; keyword is now optional so filter-only
queries ("list all my external contacts") work end-to-end.
- Each result now carries multilingual names, contact email, activation
state, whether you've chatted with them, tenant context, user
signature, and a hit-highlight line that surfaces the matched segment
and the user's department path.
- Always-empty legacy columns and fields the new backend no longer
returns are dropped.
- Also fixes the contact +get-user skill doc, which previously
instructed callers to pass --table (a flag that never existed); now
correctly documents --format table and the full --format enum.
* refactor(lark-contact): clean up search-user code, tighten skill docs
- contact_search_user.go / _test.go: simplify and clarify
- SKILL.md: focus description on user-facing trigger scenarios;
rework decision table; trim notes to load-bearing constraints
- references/lark-contact-search-user.md: add flag table covering
all four bool filters; add multi-filter examples; clean up
output field contract (drop server <h> tag implementation detail)
- references/lark-contact-get-user.md: trim to two real use cases
(self via user identity; full profile of others via bot identity);
point user-mode-by-id users to +search-user instead
- .golangci.yml: replace package-level deny on net/http with a
symbol-level forbidigo rule. Constants (http.MethodPost,
http.StatusOK) and helpers (http.StatusText) were never the
intent; only Client / NewRequest / Get / Post / Do etc. are now
blocked in shortcuts/, matching the rule's actual purpose
Change-Id: Ic42043d3f4c1b675800e48229c7ba2e970da26fe
* fix(contact +search-user): align query limit and reject empty user-ids
API rejects queries longer than 50 characters; local cap was 64 runes,
producing confusing "passed local validation but server-rejected"
behaviour. Lower the cap to 50 and rename the constant accordingly.
Also reject --user-ids inputs that parse to zero entries (",,,",
" , , ", ","): SplitCSV silently dropped empty segments, so the
shortcut sent an empty body to the API and returned indeterminate
results.
Change-Id: Ib34fe897023e175bf4c657273bdb49a33d2f083b
---------
Co-authored-by: liangshuo-1 <266696938+liangshuo-1@users.noreply.github.com>
53 lines
1.9 KiB
Go
53 lines
1.9 KiB
Go
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package contact
|
|
|
|
import "testing"
|
|
|
|
func TestPickUserName_PriorityOrder(t *testing.T) {
|
|
tests := []struct {
|
|
desc string
|
|
in map[string]interface{}
|
|
want string
|
|
}{
|
|
{"name takes precedence", map[string]interface{}{"name": "A", "user_name": "B"}, "A"},
|
|
{"user_name when name empty", map[string]interface{}{"name": "", "user_name": "B"}, "B"},
|
|
{"display_name fallback", map[string]interface{}{"display_name": "C"}, "C"},
|
|
{"employee_name fallback", map[string]interface{}{"employee_name": "D"}, "D"},
|
|
{"cn_name fallback", map[string]interface{}{"cn_name": "E"}, "E"},
|
|
{"non-string values are skipped", map[string]interface{}{"name": 42, "user_name": "F"}, "F"},
|
|
{"nothing matches → empty string", map[string]interface{}{"unknown": "X"}, ""},
|
|
{"empty map → empty string", map[string]interface{}{}, ""},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.desc, func(t *testing.T) {
|
|
if got := pickUserName(tt.in); got != tt.want {
|
|
t.Errorf("got %q, want %q", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFirstNonEmpty(t *testing.T) {
|
|
tests := []struct {
|
|
desc string
|
|
in map[string]interface{}
|
|
keys []string
|
|
want string
|
|
}{
|
|
{"first key wins", map[string]interface{}{"a": "x", "b": "y"}, []string{"a", "b"}, "x"},
|
|
{"falls through empty string", map[string]interface{}{"a": "", "b": "y"}, []string{"a", "b"}, "y"},
|
|
{"non-string values are skipped", map[string]interface{}{"a": 42, "b": "z"}, []string{"a", "b"}, "z"},
|
|
{"all empty / missing → empty string", map[string]interface{}{"a": ""}, []string{"a", "b"}, ""},
|
|
{"no keys requested → empty string", map[string]interface{}{"a": "x"}, nil, ""},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.desc, func(t *testing.T) {
|
|
if got := firstNonEmpty(tt.in, tt.keys...); got != tt.want {
|
|
t.Errorf("got %q, want %q", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|