@clawhub-ye1358215818-297cc5eb1c
Automation skill for Zoe飞书媒体发送.
---
name: feishu-media
description: 飞书媒体文件发送skill,支持发送图片到飞书群或个人.用于发送截图、设计图等场景.
version: 1.0.0
author: Zoe
license: MIT
# 飞书媒体发送 Skill
## 简介
本skill提供将本地图片发送到飞书群或个人聊天的功能。
## 什么时候用
- 用户说"发图片"、"发送图片"、"发到飞书"
- 用户需要把本地图片发送到飞书群
## 安装依赖
```bash
pip install requests
```
## 安全配置 ⚠️ 重要
**必须配置飞书凭证,建议使用环境变量,切勿硬编码!**
### 方式一:环境变量(推荐)
```bash
# Windows
set FEISHU_APP_ID=你的AppID
set FEISHU_APP_SECRET=你的AppSecret
# Linux/Mac
export FEISHU_APP_ID=你的AppID
export FEISHU_APP_SECRET=你的AppSecret
```
### 方式二:命令行参数
```python
send_image(
image_path="C:/path/to/image.png",
chat_id="oc_xxx",
app_id="cli_xxx", # 你的App ID
app_secret="xxx" # 你的App Secret
)
```
## 使用方法
### 发送图片
```python
from feishu_image import send_image
# 方式一:环境变量配置后
send_image(
image_path="C:/path/to/image.png",
chat_id="oc_xxx" # 群聊ID
)
# 方式二:命令行传入
# python feishu_image.py <图片路径> <chat_id> <app_id> <app_secret>
```
### 参数说明
| 参数 | 说明 | 必填 | 示例 |
|------|------|------|------|
| image_path | 图片本地路径 | 是 | C:/Users/admin/Desktop/xxx.png |
| chat_id | 接收者ID | 是 | oc_xxx (群) 或 ou_xxx (个人) |
| app_id | 飞书应用ID | 否 | cli_xxx(环境变量优先) |
| app_secret | 飞书应用密钥 | 否 | xxx(环境变量优先) |
## 获取飞书凭证
### 1. 创建飞书应用
1. 登录 [飞书开放平台](https://open.feishu.cn/)
2. 创建企业自建应用
3. 获取 App ID 和 App Secret
### 2. 添加权限
在应用详情中添加以下权限:
- `im:resource` - 上传图片和文件
- `im:message:send` - 发送消息
- `im:chat:send` - 发送群消息
### 3. 获取chat_id
- 群聊:在群设置中查看群ID
- 个人:获取用户的 open_id
## 示例
### 发送UI设计图
```python
send_image(
image_path="C:/Users/admin/Desktop/battery-ui.png",
chat_id="oc_205333d14cf0881ef8b79fa223ff902b"
)
```
### 发送文件(扩展)
```python
# 发送文件类似,只需改用 file 相关API
```
## 注意事项 ⚠️
1. **安全**:不要将包含真实凭证的代码提交到公开仓库!
2. **权限**:飞书应用需要开启相应权限才能使用
3. **图片格式**:支持 JPEG, PNG, WEBP, GIF, BMP 等
4. **文件大小**:最大 30MB
5. **频率限制**:注意飞书API的调用频率限制
## 故障排除
### 错误码 230001
- 原因:无效的请求内容
- 解决:检查image_key是否正确
### 错误码 99991663
- 原因:应用没有权限
- 解决:在飞书开放平台给应用添加对应权限
### 错误码 230013
- 原因:机器人对该用户不可用
- 解决:用户需要先与机器人建立会话
## 更新日志
- v1.0.0 (2026-03-19): 初始版本,支持发送图片
FILE:scripts/feishu_image.py
# -*- coding: utf-8 -*-
"""
飞书图片发送模块
注意:此模块需要用户自行配置app_id和app_secret,切勿提交包含真实凭证的代码!
"""
import os
import json
def get_feishu_config():
"""
从环境变量或配置文件获取飞书凭证
建议使用环境变量,不要硬编码!
环境变量:
FEISHU_APP_ID: 飞书应用ID
FEISHU_APP_SECRET: 飞书应用密钥
"""
app_id = os.environ.get("FEISHU_APP_ID")
app_secret = os.environ.get("FEISHU_APP_SECRET")
if not app_id or not app_secret:
raise Exception("请配置FEISHU_APP_ID和FEISHU_APP_SECRET环境变量")
return app_id, app_secret
def send_image(image_path: str, chat_id: str, app_id: str = None, app_secret: str = None):
"""
发送图片到飞书群或个人
Args:
image_path: 图片本地路径
chat_id: 飞书群ID或个人ID
app_id: 飞书应用ID (可选,从环境变量读取)
app_secret: 飞书应用密钥 (可选,从环境变量读取)
"""
# 从参数或环境变量获取凭证
if not app_id or not app_secret:
app_id, app_secret = get_feishu_config()
# 动态导入,避免全局依赖
import requests
BASE_URL = "https://open.feishu.cn/open-apis"
access_token = None
def get_access_token():
nonlocal access_token
if access_token:
return access_token
url = f"{BASE_URL}/auth/v3/tenant_access_token/internal"
headers = {"Content-Type": "application/json"}
data = {
"app_id": app_id,
"app_secret": app_secret
}
response = requests.post(url, headers=headers, json=data)
result = response.json()
if result.get("code") != 0:
raise Exception(f"获取access_token失败: {result}")
access_token = result["tenant_access_token"]
return access_token
def get_headers():
token = get_access_token()
return {"Authorization": f"Bearer {token}"}
# 1. 上传图片
print(f"[INFO] 上传图片: {image_path}")
with open(image_path, "rb") as f:
files = {
"image": (os.path.basename(image_path), f, "application/octet-stream")
}
data = {"image_type": "message"}
upload_url = f"{BASE_URL}/im/v1/images"
response = requests.post(upload_url, files=files, data=data, headers=get_headers())
result = response.json()
print(f"[DEBUG] Upload image response: {result}")
if result.get("code") != 0:
raise Exception(f"上传图片失败: {result}")
image_key = result.get("data", {}).get("image_key")
print(f"[INFO] 图片key: {image_key}")
# 2. 发送图片
print(f"[INFO] 发送图片到: {chat_id}")
send_url = f"{BASE_URL}/im/v1/messages"
params = {"receive_id_type": "chat_id"}
content = json.dumps({"image_key": image_key})
data = {
"receive_id": chat_id,
"msg_type": "image",
"content": content
}
response = requests.post(send_url, headers=get_headers(), params=params, json=data)
result = response.json()
print(f"[DEBUG] Send image response: {result}")
if result.get("code") != 0:
raise Exception(f"发送图片失败: {result}")
print(f"[INFO] 发送成功!")
return result
if __name__ == "__main__":
import sys
if len(sys.argv) < 3:
print("用法: python feishu_image.py <图片路径> <chat_id>")
print("环境变量: FEISHU_APP_ID, FEISHU_APP_SECRET")
sys.exit(1)
image_path = sys.argv[1]
chat_id = sys.argv[2]
# 可以从命令行传参,也可以设置环境变量
cmd_app_id = sys.argv[3] if len(sys.argv) > 3 else None
cmd_secret = sys.argv[4] if len(sys.argv) > 4 else None
send_image(image_path, chat_id, cmd_app_id, cmd_secret)
FILE:scripts/send-image.js
import { uploadImageFeishu, sendImageFeishu } from "../../../feishu/src/media.js";
/**
* @param {object} params
* @param {string} params.imagePath - 本地图片路径
* @param {string} params.chatId - 飞书群ID或个人ID
* @param {object} params.cfg - OpenClaw配置
*/
export async function sendImageToFeishu({ imagePath, chatId, cfg }) {
// 1. 上传图片到飞书
const { imageKey } = await uploadImageFeishu({
cfg,
image: imagePath,
imageType: "message",
});
// 2. 发送图片
const result = await sendImageFeishu({
cfg,
to: chatId,
imageKey,
});
return result;
}