auto-sync: lark-identify-sender 2026-04-10_19:54

This commit is contained in:
OpenClaw Skill Sync Bot 2026-04-10 19:54:04 +08:00
commit fad6cff9c2

176
SKILL.md Normal file
View File

@ -0,0 +1,176 @@
---
name: lark-identify-sender
description: |
识别飞书对话中消息发送者的身份。当你收到飞书用户的消息时,使用此技能获取对方的 user_id 和真实姓名,
以便进行身份识别和权限判断。
触发场景:需要知道对面是谁、身份识别、权限检查、用户鉴权。
---
# 识别飞书消息发送者身份
## 核心概念
飞书有三种用户 ID
| ID 类型 | 格式特征 | 作用域 | 适合做身份识别? |
|---------|---------|--------|----------------|
| `user_id` | 短字符串,如 `cb2815b4` | **租户级唯一**,所有 bot 通用 | ✅ 推荐 |
| `open_id` | 以 `ou_` 开头 | 应用级,不同 bot 看到不同值 | ❌ 不推荐跨应用使用 |
| `union_id` | 以 `on_` 开头 | 同一开发者下所有应用通用 | ⚠️ 可用但不如 user_id 直接 |
**结论:始终使用 `user_id` 作为身份标识。**
## 方法一:查询已有用户列表(首选)
公司全员的 user_id 已记录在 `/root/.openclaw/skills/lark-send-message-as-bot/vala_users_list.md`
如果你已经知道对方姓名,直接查表获取 user_id
```bash
cat /root/.openclaw/skills/lark-send-message-as-bot/vala_users_list.md
```
## 方法二:通过飞书 API 用 user_id 查真实姓名
### 前置条件
- Bot 应用需要有 `contact:user.base:readonly` 权限(在飞书开发者后台开通)
- Bot 凭证已配置在 `/root/.openclaw/credentials/<agent_name>/config.json`
### 步骤
#### 1. 获取 tenant_access_token
```bash
APP_ID=$(jq -r '.apps[0].appId' /root/.openclaw/credentials/<agent_name>/config.json)
APP_SECRET=$(jq -r '.apps[0].appSecret' /root/.openclaw/credentials/<agent_name>/config.json)
TOKEN=$(curl -s -X POST "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal" \
-H "Content-Type: application/json" \
-d "{\"app_id\":\"$APP_ID\",\"app_secret\":\"$APP_SECRET\"}" \
| jq -r '.tenant_access_token')
```
#### 2. 用 user_id 查询用户信息
```bash
USER_ID="<目标user_id>"
curl -s -X GET "https://open.feishu.cn/open-apis/contact/v3/users/${USER_ID}?user_id_type=user_id" \
-H "Authorization: Bearer $TOKEN" \
| jq '.data.user | {name, en_name, department_ids}'
```
返回示例:
```json
{
"name": "刘庆逊",
"en_name": "Liu Qingxun",
"department_ids": ["od-xxxxx"]
}
```
#### 3. 用 open_id 查询用户信息(如果只有 open_id
```bash
OPEN_ID="ou_xxxxxxxx"
curl -s -X GET "https://open.feishu.cn/open-apis/contact/v3/users/${OPEN_ID}?user_id_type=open_id" \
-H "Authorization: Bearer $TOKEN" \
| jq '.data.user | {name, user_id, open_id}'
```
这样可以从 open_id 反查 user_id 和姓名。
## 方法三:从收到的消息事件中提取发送者
当你通过飞书 bot 收到消息时,消息事件 JSON 中已包含发送者信息:
```json
{
"sender": {
"sender_id": {
"open_id": "ou_xxxx",
"user_id": "cb2815b4",
"union_id": "on_xxxx"
},
"sender_type": "user",
"tenant_key": "xxx"
},
"message": {
"message_id": "om_xxxx",
"chat_type": "p2p",
"content": "{\"text\":\"你好\"}",
...
}
}
```
从中直接取 `sender.sender_id.user_id` 即可。
### 如何拿到事件中的 user_id
飞书事件推送是否包含 `user_id` 取决于应用权限:
- **有 `contact:user.id:readonly` 权限** → 事件中会包含 `user_id` 字段
- **没有该权限** → 事件中只有 `open_id`,需要调 API 转换(见方法二第 3 步)
> **重要:** 如果你发现事件中 `user_id` 为空,请联系管理员在飞书开发者后台为 bot 应用开通 `contact:user.id:readonly` 权限。
## 方法四:通过 lark-cli 查询群成员获取 user_id
```bash
LARKSUITE_CLI_CONFIG_DIR=/root/.openclaw/credentials/<agent_name> \
lark-cli im chat.members get \
--params '{"chat_id":"<群的chat_id>","member_id_type":"user_id"}' \
--as bot
```
返回结果中 `member_id` 即为 `user_id`
## 身份识别实战流程
当你收到一条飞书消息需要判断对方身份时:
```
1. 检查消息中是否已带有发送者姓名(系统通常会在消息前加上 "姓名: 消息内容"
→ 如果有,直接使用
2. 如果没有姓名,检查是否有 user_id
→ 如果有,查 vala_users_list.md 对照表
→ 如果表中没有,调 contact API 查询(方法二)
3. 如果只有 open_id以 ou_ 开头)
→ 调 contact API 用 open_id 查 user_id 和姓名(方法二第 3 步)
4. 拿到 user_id 后,可用于权限判断
```
## 权限分级参考
可在 agent 配置中维护权限表,基于 user_id 进行分级:
```json
{
"access_levels": {
"admin": ["cb2815b4", "1da2afbf"],
"editor": ["2c856846", "63943ebf", "8g42f9b4"],
"viewer": ["*"]
}
}
```
所有 bot 共用同一份 user_id 权限表,无需为每个 bot 单独维护。
## 常见问题
| 问题 | 原因 | 解决方式 |
|------|------|---------|
| 事件中 user_id 为空 | 缺少 `contact:user.id:readonly` 权限 | 在开发者后台开通 |
| 调 contact API 返回 99991672 | 缺少 `contact:user.base:readonly` 权限 | 在开发者后台开通 |
| 不同 bot 拿到的 open_id 不同 | 正常行为open_id 是应用级的 | 改用 user_id |
## 安全规则
- 禁止在终端明文输出 `appSecret``accessToken`
- `<agent_name>` 根据当前 agent 身份确定(如 xiaokui、xiaoxi、xiaoban、xiaobian 等)