From fad6cff9c280bdf8cefc9e3851b9ae39698dcf0f Mon Sep 17 00:00:00 2001 From: OpenClaw Skill Sync Bot Date: Fri, 10 Apr 2026 19:54:04 +0800 Subject: [PATCH] auto-sync: lark-identify-sender 2026-04-10_19:54 --- SKILL.md | 176 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 SKILL.md diff --git a/SKILL.md b/SKILL.md new file mode 100644 index 0000000..13fba91 --- /dev/null +++ b/SKILL.md @@ -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//config.json` + +### 步骤 + +#### 1. 获取 tenant_access_token + +```bash +APP_ID=$(jq -r '.apps[0].appId' /root/.openclaw/credentials//config.json) +APP_SECRET=$(jq -r '.apps[0].appSecret' /root/.openclaw/credentials//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/ \ + 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 身份确定(如 xiaokui、xiaoxi、xiaoban、xiaobian 等)