Skill: shyzhen/dingtalk-send-media (version 1.0.1)

--- name: dingtalk-send-media description: 发送钉钉媒体文件给用户或群聊。仅在用户明确要求把本地文件、截图、录音、视频、附件发送到钉钉，或当前上下文已明确是钉钉会话时使用。通过 `scripts/send_media.py` 执行，支持 image/voice/video/file 等。 metadata: { "openclaw": { "emoji": "📤", "requires": { "anyBins": ["python", "python3"] }, }, } --- # DingTalk Send Media 使用同目录脚本 `scripts/send_media.py` 发送钉钉媒体消息。OpenClaw 不会自动执行目录中的 `.py` 文件；命中本 skill 后，应显式调用脚本。 ## 触发场景 在这些场景使用本 skill： - 用户要求把本地文件、图片、截图、录音、视频、压缩包发到钉钉 - 用户要求发送给某个钉钉用户 ID，或发送到某个钉钉群 ID - 当前上下文已明确是钉钉账号或钉钉会话，且目标是“发送附件” 不要在这些场景使用本 skill： - 用户想编辑钉钉文档正文或知识库内容 - 用户只说“发给他”但没有文件路径、目标 ID，且上下文无法补全 - 与钉钉无关的发送场景，例如邮件附件、飞书文件、Slack 上传 ## 运行前提 脚本依赖 `python` 或 `python3`。 可用配置来源： 1. 环境变量 `DINGTALK_CLIENTID` + `DINGTALK_CLIENTSECRET`，优先级最高 2. `openclaw.json` 中的 `channels.dingtalk.accounts` 3. `openclaw.json` 中的 `channels.dingtalk-connector.accounts` 4. `openclaw.json` 中的 `channels.dingtalk-connector` 顶层凭证 相关环境变量： - `DINGTALK_CLIENTID` - `DINGTALK_CLIENTSECRET` - `DINGTALK_ROBOTCODE` - `DINGTALK_CORPID` - `DINGTALK_AGENTID` - `OPENCLAW_AGENT_ID` - `OPENCLAW_ACCOUNT_ID` - `OPENCLAW_CONFIG` ## 执行入口 脚本文件：`scripts/send_media.py` 执行时使用绝对路径，形式如下： ```bash python /absolute/path/to/scripts/send_media.py <file-path> <target-id> [account-id] [media-type] [--group|--user] [--debug] ``` 在 Linux 或 macOS 上，如果只有 `python3`，使用： ```bash python3 /absolute/path/to/scripts/send_media.py <file-path> <target-id> [account-id] [media-type] [--group|--user] [--debug] ``` ## 发送前检查 执行前尽量确认这些信息： - 文件路径存在，且是本机可访问的绝对路径 - 目标 ID 是钉钉用户 ID，或以 `cid` 开头的群 ID - 如果存在多个钉钉账号，确认应该使用哪个账号 - 如果用户没有指定媒体类型，可以让脚本自动检测 - 默认会将 `cid...` 自动识别为群聊；如需覆盖，可使用 `--group` 或 `--user` ## 命令映射 ### 1. 自动检测账号并发送 适用： - 当前只有一个账号 - 或者已能从 `OPENCLAW_AGENT_ID` / `OPENCLAW_ACCOUNT_ID` / bindings 推导账号 执行： ```bash python /absolute/path/to/scripts/send_media.py <file-path> <target-id> ``` 说明： - 若 `target-id` 以 `cid` 开头，脚本会自动按群聊发送 - 其他目标默认按单聊发送 ### 2. 指定账号发送 适用： - 存在多个钉钉账号 - 用户明确要求用某个账号发送 执行： ```bash python /absolute/path/to/scripts/send_media.py <file-path> <target-id> <account-id> ``` ### 3. 指定媒体类型发送 适用： - 自动检测类型不可靠 - 用户明确要求按图片、语音、视频或普通文件发送 执行： ```bash python /absolute/path/to/scripts/send_media.py <file-path> <target-id> <account-id-or-type> [media-type] ``` 媒体类型仅允许： - `image` - `voice` - `video` - `file` ### 4. 显式指定群聊或单聊 适用： - 目标 ID 规则不稳定，不能只靠 `cid` 判断 - 你想覆盖自动检测结果 执行： ```bash python /absolute/path/to/scripts/send_media.py <file-path> <target-id> [account-id] [media-type] --group python /absolute/path/to/scripts/send_media.py <file-path> <target-id> [account-id] [media-type] --user ``` ### 5. 调试模式 适用： - 账号检测或配置选择异常 执行： ```bash python /absolute/path/to/scripts/send_media.py <file-path> <target-id> --debug ``` ## 工作流程 1. 确认目标是钉钉发送媒体，而不是文档编辑。 2. 提取文件路径和目标 ID。 3. 如有多个账号或上下文不明确，优先确认账号。 4. 执行脚本。 5. 若脚本返回 `ok: true`，向用户报告已发送的文件名、目标和账号。 6. 若脚本返回 `ok: false`，根据错误内容给出下一步说明。 ## 常见错误 - `未找到 OpenClaw 配置文件 openclaw.json`：当前无配置文件，需提供环境变量凭证或配置文件 - `未找到钉钉账号配置`：账号自动检测失败，需显式指定账号或补齐配置 - `获取 access token 失败`：检查 `clientId` / `clientSecret` - `上传媒体文件失败`：检查文件路径、大小、媒体类型和上传权限 - `发送消息失败`：检查目标用户 ID / 群 ID、机器人权限和 `robotCode` ## 限制 - 本 skill 用于发送媒体，不用于编辑钉钉文档内容 - 需要本机已有可发送的文件路径 - 群聊发送要求目标是合法 `cid...` - 多账号场景下，若无法唯一推导账号，可能需要显式传入 `account-id` ## 参考 - 人工说明文档：`README.md` - 实际执行脚本：`scripts/send_media.py`

path: README.md
content: # 钉钉媒体文件发送技能 (dingtalk-send-media)

发送钉钉媒体文件（图片/语音/视频/文件）给用户。支持从环境变量或 OpenClaw 配置自动检测账号，跨平台支持。

> 背景：我在使用openclaw和钉钉的官方连接器，但是他们不支持这些功能（最新版本0.8.13）。
>
> 这是我的issue： https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/issues/456
>
> [于是有了这个玩具。](https://clawhub.ai/shyzhen/dingtalk-send-media)

---

## 🚀 快速开始

### 1. 配置钉钉凭证

**方式 1：编辑 `~/.openclaw/.env` 文件（推荐，优先级最高）**

OpenClaw 会在启动时自动加载此文件中的环境变量。

```bash
# ~/.openclaw/.env
DINGTALK_CLIENTID=dingxxxxxx
DINGTALK_CLIENTSECRET=your_secret
DINGTALK_ROBOTCODE=dingxxxxxx  # 可选，默认同 clientId
```

**方式 2：编辑 `~/.openclaw/openclaw.json` 配置文件**

```json5
{
  "channels": {
    "dingtalk-connector": {
      "accounts": {
        "prd_bot": {
          "clientId": "dingxxxxxx",
          "clientSecret": "your_secret",
          "robotCode": "dingxxxxxx"
        }
      }
    }
  },
  "bindings": [
    {
      "agentId": "main",
      "match": {
        "channel": "dingtalk-connector",
        "accountId": "prd_bot"
      }
    }
  ]
}
```

**方式 3：配置文件 + 环境变量占位符**

```json5
{
  "channels": {
    "dingtalk": {
      "accounts": {
        "prd_bot": {
          "clientId": "${DINGTALK_CLIENTID}",
          "clientSecret": "${DINGTALK_CLIENTSECRET}"
        }
      }
    }
  }
}
```

**获取凭证：**
1. 登录 [钉钉开放平台](https://open.dingtalk.com/)
2. 进入「应用开发」→「企业内部开发」
3. 创建或选择已有应用
4. 在「应用详情」页面获取 `AppKey` (ClientId) 和 `AppSecret` (ClientSecret)

**注意：** 修改 `.env` 文件后需要重启 OpenClaw Gateway 才能生效。

---

### 2. 配置优先级

| 方式 | 优先级 | 适用场景 |
|------|--------|----------|
| 环境变量 `DINGTALK_*` | ⭐⭐⭐ 最高 | 临时切换、CI/CD、Docker |
| 配置文件 `${VAR}` 占位符 | ⭐⭐ 中 | 统一配置管理 |
| 配置文件显式值 | ⭐ 低 | 固定配置 |

**说明：** 环境变量优先级最高，设置后会覆盖配置文件中的值。

---

### 3. 申请应用权限

在钉钉开放平台「权限管理」中申请以下权限：

| 权限码 | 用途 | 必需 |
|--------|------|------|
| 机器人消息发送相关权限 | 发送消息给用户 | ✅ |
| 媒体文件上传相关权限 | 上传文件/图片/视频 | ✅ |

**申请步骤：**
1. 进入应用管理页面
2. 点击「权限管理」
3. 搜索上述权限码并申请
4. 等待管理员审批通过

---

### 4. 验证配置

重启 OpenClaw Gateway 后，可以通过以下方式验证配置是否生效：

```bash
# 检查环境变量是否加载
openclaw env | Select-String DINGTALK

# 或查看 Gateway 日志
openclaw logs --grep DINGTALK
```

---

## ✨ 核心特性

- ✅ **自动账号检测** - 从环境变量、`OPENCLAW_AGENT_ID`、bindings 或配置文件自动推导钉钉账号
- ✅ **零依赖** - 仅使用 Python 标准库，无需 `curl`/`jq`
- ✅ **跨平台** - Windows/Linux/macOS 通用
- ✅ **多媒体支持** - 自动检测 `image` / `voice` / `video` / `file`
- ✅ **正确的文件名** - 自动传递 `fileName` 参数，避免显示 `#fileName#`

---

## 📖 使用方法

### 方式 1：直接调用脚本（推荐）

```bash
# 进入技能目录
cd ~/.openclaw/skills/dingtalk-send-media

# 发送文件（自动检测账号）
python scripts/send_media.py <文件路径> <目标 ID>

# 发送文件（指定账号）
python scripts/send_media.py <文件路径> <目标 ID> [账号 ID] [媒体类型] [--group|--user] [--debug]
```

**参数说明：**
- `文件路径`: 本地文件的绝对路径
- `目标 ID`: 钉钉用户 ID（如 `300523656829570034`）或群 ID（以 `cid` 开头）
- `账号 ID`: OpenClaw 配置中的钉钉账号 ID（可选，默认自动检测）
- `媒体类型`: `image` / `voice` / `video` / `file`（可选，默认自动检测）
- `--group` / `--user`: 显式指定按群聊或单聊发送；默认会把 `cid...` 自动识别为群聊
- `--debug`: 输出账号检测和目标类型判断过程

### 方式 2：在对话中使用

告诉模型你要发送的文件，模型会自动调用脚本。

**示例：**
```bash
# 自动检测账号，发送文件
python scripts/send_media.py "C:/path/to/file.pdf" "300523656829570034"

# 指定账号发送
python scripts/send_media.py "C:/path/to/image.png" "300523656829570034" prd_bot

# 指定媒体类型
python scripts/send_media.py "C:/path/photo.jpg" "300523656829570034" prd_bot image

# 发送到群聊
python scripts/send_media.py "C:/path/to/meeting.mp4" "cidxxxxxxxx" dev_bot video

# 显式指定按群聊发送
python scripts/send_media.py "C:/path/to/meeting.mp4" "some_target_id" dev_bot video --group
```

---

## 🎯 典型场景

### 场景 1：发送报告文件

**用户**: "把昨天的销售报告发给我"

**模型**:
```bash
python scripts/send_media.py "C:/path/to/reports/sales_report_2026-04-06.pdf" "300523656829570034"
```

### 场景 2：发送截图

**用户**: "把这个错误的截图发给我看看"

**模型**:
```bash
python scripts/send_media.py "C:/path/to/screenshots/error_2026-04-07.png" "300523656829570034"
```

### 场景 3：发送到群聊

**用户**: "把会议纪要发到项目群"

**模型**:
```bash
python scripts/send_media.py "C:/path/to/meeting_notes.docx" "cidxxxxxxxx" prd_bot file
```

### 场景 4：发送语音/视频

**用户**: "把这个录音发给客户"

**模型**:
```bash
python scripts/send_media.py "C:/path/to/recording.mp3" "300523656829570034" prd_bot voice
```

---

## ⚠️ 注意事项

### 文件大小限制

| 类型 | 最大大小 |
|------|---------|
| 文件 | 20MB |
| 图片 | 10MB |
| 语音 | 2MB |
| 视频 | 20MB |

### 支持的文件格式

- **文件**：PDF, DOCX, XLSX, PPTX, TXT, ZIP 等
- **图片**：JPG, PNG, GIF, BMP, WEBP
- **语音**：MP3, WAV, AMR
- **视频**：MP4, AVI, MOV, WMV

### 目标 ID 格式

- **用户 ID**: 钉钉用户 ID（如 `300523656829570034`）
- **群 ID**: 以 `cid` 开头（如 `cidxxxxxxxx`）
- **自动检测规则**: 目标 ID 以 `cid` 开头时，脚本默认按群聊发送；否则默认按单聊发送

---

## 🐛 故障排除

### 问题 1: 找不到配置文件

```
错误：未找到 OpenClaw 配置文件 openclaw.json
```

**解决**: 
- 确认 `~/.openclaw/openclaw.json` 存在
- 或直接设置 `DINGTALK_CLIENTID` 和 `DINGTALK_CLIENTSECRET` 环境变量

### 问题 2: 获取 access token 失败

```
错误：获取 access token 失败：...
```

**解决**: 
- 检查 `clientId` 和 `clientSecret` 是否正确
- 确认钉钉应用已发布

### 问题 3: 上传文件失败

```
错误：上传媒体文件失败：...
```

**解决**: 
- 确认文件路径正确且文件存在
- 确认文件大小不超过限制
- 确认钉钉应用有媒体上传权限

### 问题 4: 发送消息失败

```
错误：发送消息失败：...
```

**解决**:
- 确认目标用户 ID 或群 ID 正确
- 确认机器人已添加到群聊（群聊场景）
- 确认 `robotCode` 配置正确

### 问题 5: 账号检测错误

```
错误：未找到钉钉账号配置：xxx
```

**解决**:
- 检查 `~/.openclaw/.env` 中是否设置了 `DINGTALK_CLIENTID` 和 `DINGTALK_CLIENTSECRET`
- 检查 `openclaw.json` 中的 `channels.dingtalk.accounts` 配置
- 检查 `openclaw.json` 中的 `channels.dingtalk-connector.accounts` 配置
- 检查 `bindings` 中的 `agentId → accountId` 映射
- 或在命令行显式指定账号 ID 参数

---

## 📊 与 dingtalk-file-send 对比

| 特性 | dingtalk-send-media | dingtalk-file-send |
|------|---------------------|-------------------|
| 实现语言 | Python | Bash |
| 外部依赖 | 无 | `curl`, `jq` |
| Windows 兼容 | ✅ 原生支持 | ❌ 需要 Git Bash/WSL |
| 自动账号检测 | ✅ 支持 | ✅ 支持 |
| 多媒体类型 | image/voice/video/file | 仅 file |
| OpenClaw 元数据 | ✅ 支持 | ✅ 支持 |

---

## 🔧 调试模式

使用 `--debug` 或 `-d` 参数查看账号检测过程：

```bash
python scripts/send_media.py "file.pdf" "user_id" --debug
```

输出示例：
```
[DEBUG] OPENCLAW_AGENT_ID=main
[DEBUG] OPENCLAW_ACCOUNT_ID=未设置
[DEBUG] 账号检测来源：binding:main→prd_bot
```

在 Linux 或 macOS 上，如果系统没有 `python` 命令，请改用：

```bash
python3 scripts/send_media.py "/path/to/file.pdf" "300523656829570034"
```

---

**最后更新：** 2026-04-10  
**版本：** 1.0  
**作者：** Ash


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (MEDIUM)