commit 0b0b0de311137c0ec0f7b66479b4cb303400bfd9 Author: OpenClaw Bot Date: Fri Apr 3 16:06:53 2026 +0800 auto-sync: feishu_send_file 2026-04-03_16:06 diff --git a/SKILL.md b/SKILL.md new file mode 100644 index 0000000..0b2ad5e --- /dev/null +++ b/SKILL.md @@ -0,0 +1,131 @@ +--- +name: feishu-send-file +description: | + 通过飞书API发送本地文件(Excel/PDF/Word/PPT等)到飞书用户或群组。 + 绕过OpenClaw message工具的限制,直接调用飞书原生文件上传+发送API。 +metadata: + { + "openclaw": + { + "requires": { "tools": ["exec"] }, + "categories": ["feishu", "file", "messaging"] + }, + } +--- + +# 飞书本地文件发送技能 + +## When to Use + +当用户要求将**本地文件**(Excel、PDF、Word、PPT、音视频等)通过飞书发送给某人或某个群时使用此技能。 + +> **注意**: OpenClaw 内置的 message 工具仅支持发送文本和URL媒体,不支持本地文件路径。本技能通过 `exec` 工具直接调用飞书 API 实现文件发送。 + +## Core Rules + +### 1. 确定飞书账号凭证 + +从 OpenClaw 配置文件 `/root/.openclaw/openclaw.json` 的 `channels.feishu.accounts` 中读取对应账号的 `appId` 和 `appSecret`。 + +根据当前 agent 绑定关系选择账号: +- **xiaoban** agent → 使用 `xiaoban` 账号 +- **xiaoxi** agent → 使用 `xiaoxi` 账号 + +### 2. 文件类型映射 + +根据文件扩展名确定飞书 `file_type` 参数: + +| 扩展名 | file_type | +|--------|-----------| +| `.xls` `.xlsx` | `xls` | +| `.doc` `.docx` | `doc` | +| `.pdf` | `pdf` | +| `.ppt` `.pptx` | `ppt` | +| `.mp4` `.mov` `.avi` | `mp4` | +| `.opus` `.ogg` | `opus` | +| 其他 | `stream` | + +### 3. 发送目标格式 + +- **个人**: 使用 `open_id`(格式 `ou_xxxx`),`receive_id_type` 为 `open_id` +- **群组**: 使用 `chat_id`(格式 `oc_xxxx`),`receive_id_type` 为 `chat_id` + +### 4. 执行流程(三步) + +通过 `exec` 工具执行以下 shell 脚本,**一次性完成全部三步**: + +```bash +#!/bin/bash +set -e + +# === 配置区(根据实际情况填写)=== +APP_ID="" +APP_SECRET="" +FILE_PATH="<本地文件绝对路径>" +FILE_NAME="<文件名,如 report.xlsx>" +FILE_TYPE="<文件类型,如 xls>" +RECEIVE_ID="<目标open_id或chat_id>" +RECEIVE_ID_TYPE="" + +# === Step 1: 获取 tenant_access_token === +TOKEN_RESP=$(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}\"}") + +TOKEN=$(echo "$TOKEN_RESP" | grep -o '"tenant_access_token":"[^"]*"' | cut -d'"' -f4) + +if [ -z "$TOKEN" ]; then + echo "ERROR: 获取 tenant_access_token 失败" + echo "$TOKEN_RESP" + exit 1 +fi +echo "Step 1 OK: token acquired" + +# === Step 2: 上传文件获取 file_key === +UPLOAD_RESP=$(curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/files" \ + -H "Authorization: Bearer ${TOKEN}" \ + -F "file_type=${FILE_TYPE}" \ + -F "file_name=${FILE_NAME}" \ + -F "file=@${FILE_PATH}") + +FILE_KEY=$(echo "$UPLOAD_RESP" | grep -o '"file_key":"[^"]*"' | cut -d'"' -f4) + +if [ -z "$FILE_KEY" ]; then + echo "ERROR: 文件上传失败" + echo "$UPLOAD_RESP" + exit 1 +fi +echo "Step 2 OK: file_key=${FILE_KEY}" + +# === Step 3: 发送文件消息 === +SEND_RESP=$(curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=${RECEIVE_ID_TYPE}" \ + -H "Authorization: Bearer ${TOKEN}" \ + -H "Content-Type: application/json" \ + -d "{\"receive_id\":\"${RECEIVE_ID}\",\"msg_type\":\"file\",\"content\":\"{\\\"file_key\\\":\\\"${FILE_KEY}\\\"}\"}") + +MSG_ID=$(echo "$SEND_RESP" | grep -o '"message_id":"[^"]*"' | cut -d'"' -f4) + +if [ -z "$MSG_ID" ]; then + echo "ERROR: 消息发送失败" + echo "$SEND_RESP" + exit 1 +fi +echo "Step 3 OK: message sent, message_id=${MSG_ID}" +``` + +### 5. 注意事项 + +- 文件大小上限 **30MB** +- 发送前用 `ls -la <文件路径>` 确认文件存在且大小合理 +- 如果发送音视频文件(mp4/opus),Step 3 中 `msg_type` 改为 `"media"`,content 改为 `{"file_key":"..."}` 格式不变 +- 飞书应用需要 `im:message:send_as_bot` 和 `im:resource` 权限 +- 如遇权限错误(code 99991672),返回的 msg 中通常包含权限申请链接,告知用户去审批 + +## 常见问题 + +| 问题 | 原因 | 解决 | +|------|------|------| +| token 获取失败 | appId/appSecret 错误 | 核对 openclaw.json 配置 | +| 上传返回 99991672 | 缺少 `im:resource` 权限 | 去飞书开放平台添加权限并审批 | +| 发送返回权限错误 | 缺少 `im:message:send_as_bot` | 同上 | +| 文件过大 | 超过 30MB | 压缩文件或分片 |