Files
qqbot/skills/qqbot-cron/SKILL.md
rianli 93f284891c feat(qqbot): 添加图片发送功能及优化定时任务载荷格式
新增功能:
- 新增 qqbot-media 技能,支持 <qqimg> 标签发送本地图片
- 添加图片尺寸检测工具 (image-size.ts),自动识别常见图片格式
- 支持将本地图片上传至 QQ 富媒体服务器

优化改进:
- 定时任务支持结构化 JSON 载荷格式
- 优化 <qqimg> 标签正则表达式,避免误匹配反引号内的说明文字
- 完善消息处理流程和错误处理

文件变更:
- src/gateway.ts: 添加图片处理、上传逻辑
- src/outbound.ts: 增强外发消息能力
- src/utils/image-size.ts: 新增图片尺寸解析工具
- skills/qqbot-media/SKILL.md: 新增图片功能说明文档
- skills/qqbot-cron/SKILL.md: 补充结构化载荷说明
2026-02-03 13:14:22 +08:00

538 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: qqbot-cron
description: QQ Bot 智能提醒技能。支持一次性提醒、周期性任务、自动降级确保送达。可设置、查询、取消提醒。
metadata: {"clawdbot":{"emoji":"⏰"}}
---
# QQ Bot 智能提醒
让 AI 帮用户设置、管理定时提醒,支持私聊和群聊。
---
## 🤖 AI 决策指南
> **本节专为 AI 理解设计,帮助快速决策**
### 用户意图识别
| 用户说法 | 意图 | 执行动作 |
|----------|------|----------|
| "5分钟后提醒我喝水" | 创建提醒 | `openclaw cron add` |
| "每天8点提醒我打卡" | 创建周期提醒 | `openclaw cron add --cron` |
| "我有哪些提醒" | 查询提醒 | `openclaw cron list` |
| "取消喝水提醒" | 删除提醒 | `openclaw cron remove` |
| "修改提醒时间" | 删除+重建 | 先 remove 再 add |
| "提醒我" (无时间) | **需追问** | 询问具体时间 |
### 必须追问的情况
当用户说法**缺少以下信息**时,**必须追问**
1. **没有时间**"提醒我喝水" → 询问"请问什么时候提醒你?"
2. **时间模糊**"晚点提醒我" → 询问"具体几点呢?"
3. **周期不明**"定期提醒我" → 询问"多久一次?每天?每周?"
### 无需追问可直接执行
| 用户说法 | 理解为 |
|----------|--------|
| "5分钟后" | `--at 5m` |
| "半小时后" | `--at 30m` |
| "1小时后" | `--at 1h` |
| "明天早上8点" | `--at 2026-02-02T08:00:00+08:00` |
| "每天早上8点" | `--cron "0 8 * * *"` |
| "工作日9点" | `--cron "0 9 * * 1-5"` |
---
## 📦 结构化载荷格式(新)
> **重要**定时提醒现在支持结构化载荷格式AI 只需输出 JSON代码层会自动处理 Base64 编码。
### 输出格式
当 AI 需要设置定时提醒时,可以输出以下结构化载荷:
```
QQBOT_PAYLOAD:
{
"type": "cron_reminder",
"content": "💧 喝水时间到!",
"targetType": "c2c",
"targetAddress": "xxx_user_openid",
"originalMessageId": "msg_xxx_123"
}
```
### 字段说明
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `type` | string | ✅ | 固定为 `"cron_reminder"` |
| `content` | string | ✅ | 提醒内容,触发时直接发送给用户 |
| `targetType` | string | ✅ | 目标类型:`"c2c"`(私聊)或 `"group"`(群聊) |
| `targetAddress` | string | ✅ | 目标地址user_openid 或 group_openid |
| `originalMessageId` | string | ❌ | 原始消息 ID可选用于追踪 |
### 处理流程
1. AI 输出 `QQBOT_PAYLOAD:` + JSON 格式的载荷
2. 代码层检测并解析载荷
3. 代码层将 JSON 编码为 Base64
4. 代码层调用 `openclaw cron add --message "QQBOT_CRON:{base64}"`
5. 触发时解码 Base64根据 targetType 和 targetAddress 发送 content
> ⚠️ **注意**:结构化载荷方式目前仍在完善中,推荐继续使用下面的命令行方式。
---
## 📋 命令速查
### 创建提醒(完整模板)
```bash
openclaw cron add \
--name "{任务名}" \
--at "{时间}" \
--session isolated \
--message "🔔 {提醒内容}时间到!" \
--deliver \
--channel qqbot \
--to "{openid}" \
--delete-after-run
```
> ⚠️ **极其重要**
> - `--message` 参数直接写最终要发送的提醒内容
> - 提醒内容格式:`🔔 {内容}时间到!`
> - **不要**使用 `--system-prompt` 或 `--system-event`cron 不支持这些参数)
> - 保持消息简洁,如:`🔔 喝水时间到!`、`📅 开会时间到!`
> ⚠️ **注意**`cron add` 命令不支持 `--reply-to` 参数。提醒消息将作为主动消息直接发送给用户。
### 查询提醒列表
```bash
openclaw cron list
```
### 删除提醒
```bash
openclaw cron remove {jobId}
```
### 立即发送消息(主动消息)
```bash
openclaw message send \
--channel qqbot \
--target "{openid}" \
--message "{消息内容}"
```
### 立即发送消息(被动回复)
```bash
openclaw message send \
--channel qqbot \
--target "{openid}" \
--reply-to "{message_id}" \
--message "{消息内容}"
```
> ⚠️ **注意**`--reply-to` 仅在 `message send` 命令中支持,且 message_id 必须在 1 小时内有效。定时提醒不支持被动回复。
---
## 💬 用户交互模板
> **创建提醒后的反馈要简洁友好,不要啰嗦**
### 创建成功反馈(推荐简洁版)
**一次性提醒**
```
⏰ 好的,{时间}后提醒你{提醒内容}~
```
**周期提醒**
```
⏰ 收到,{周期描述}提醒你{提醒内容}~
```
### 查询提醒反馈
```
📋 你的提醒:
1. ⏰ {提醒名} - {时间}
2. 🔄 {提醒名} - {周期}
说"取消xx提醒"可删除~
```
### 无提醒时反馈
```
📋 目前没有提醒哦~
说"5分钟后提醒我xxx"试试?
```
### 删除成功反馈
```
✅ 已取消"{提醒名称}"
```
---
## ⏱️ 时间格式
### 相对时间(--at
> ⚠️ **不要加 + 号!** 用 `5m` 而不是 `+5m`
| 用户说法 | 参数值 |
|----------|--------|
| 5分钟后 | `5m` |
| 半小时后 | `30m` |
| 1小时后 | `1h` |
| 2小时后 | `2h` |
| 明天这时候 | `24h` |
### 绝对时间(--at
| 用户说法 | 参数值 |
|----------|--------|
| 今天下午3点 | `2026-02-01T15:00:00+08:00` |
| 明天早上8点 | `2026-02-02T08:00:00+08:00` |
| 2月14日中午 | `2026-02-14T12:00:00+08:00` |
### Cron 表达式(--cron
| 用户说法 | Cron 表达式 | 必须加 `--tz "Asia/Shanghai"` |
|----------|-------------|------------------------------|
| 每天早上8点 | `0 8 * * *` | ✅ |
| 每天晚上10点 | `0 22 * * *` | ✅ |
| 每个工作日早上9点 | `0 9 * * 1-5` | ✅ |
| 每周一早上9点 | `0 9 * * 1` | ✅ |
| 每周末上午10点 | `0 10 * * 0,6` | ✅ |
| 每小时整点 | `0 * * * *` | ✅ |
---
## 📌 参数说明
### 必填参数
| 参数 | 说明 | 示例 |
|------|------|------|
| `--name` | 任务名,含用户标识 | `"喝水提醒"` |
| `--at` / `--cron` | 触发时间(二选一) | `5m` / `0 8 * * *` |
| `--session isolated` | 隔离会话 | 固定值 |
| `--message` | **提醒内容**(见下方模板) | `"🔔 喝水时间到!"` |
| `--deliver` | 启用投递 | 固定值 |
| `--channel qqbot` | QQ 渠道 | 固定值 |
| `--to` | 接收者 openid | 从系统消息获取 |
### 推荐参数
| 参数 | 说明 | 何时使用 |
|------|------|----------|
| `--delete-after-run` | 执行后删除 | **一次性任务必须** |
| `--tz "Asia/Shanghai"` | 时区 | **周期任务必须** |
### --message 提醒内容模板(最关键)
> ⚠️ **`--message` 的内容会直接发送给用户**,所以要写清楚提醒内容!
**模板格式**
```
--message "🔔 {提醒内容}时间到!"
```
**示例**
- 喝水:`--message "💧 喝水时间到!"`
- 开会:`--message "📅 开会时间到!"`
- 打卡:`--message "🌅 打卡时间到!"`
- 日报:`--message "📝 写日报时间到!"`
**为什么这样写?**
- 消息内容会直接发送,不经过 AI 处理
- 保持简洁,一目了然
---
## 🎯 使用场景示例
### 场景1一次性提醒
**用户**: 5分钟后提醒我喝水
**AI 执行**:
```bash
openclaw cron add \
--name "喝水提醒" \
--at "5m" \
--session isolated \
--message "💧 喝水时间到!" \
--deliver \
--channel qqbot \
--to "{openid}" \
--delete-after-run
```
**AI 回复**:
```
⏰ 好的5分钟后提醒你喝水~
```
**5分钟后用户收到**:
```
💧 喝水时间到!
```
---
### 场景2每日周期提醒
**用户**: 每天早上8点提醒我打卡
**AI 执行**:
```bash
openclaw cron add \
--name "打卡提醒" \
--cron "0 8 * * *" \
--tz "Asia/Shanghai" \
--session isolated \
--message "🌅 打卡时间到!" \
--deliver \
--channel qqbot \
--to "{openid}"
```
**AI 回复**:
```
⏰ 收到每天早上8点提醒你打卡~
```
> 💡 周期任务**不加** `--delete-after-run`
---
### 场景3工作日提醒
**用户**: 工作日下午6点提醒我写日报
**AI 执行**:
```bash
openclaw cron add \
--name "日报提醒" \
--cron "0 18 * * 1-5" \
--tz "Asia/Shanghai" \
--session isolated \
--message "📝 写日报时间到!" \
--deliver \
--channel qqbot \
--to "{openid}"
```
**AI 回复**:
```
⏰ 收到工作日下午6点提醒你写日报~
```
---
### 场景4会议提醒
**用户**: 3分钟后提醒我开会
**AI 执行**:
```bash
openclaw cron add \
--name "开会提醒" \
--at "3m" \
--session isolated \
--message "📅 开会时间到!" \
--deliver \
--channel qqbot \
--to "{openid}" \
--delete-after-run
```
**AI 回复**:
```
⏰ 好的3分钟后提醒你开会~
```
**3分钟后用户收到**:
```
📅 开会时间到!
```
---
### 场景5群组提醒
**用户**(群聊): 每天早上9点提醒大家站会
**AI 执行**:
```bash
openclaw cron add \
--name "站会提醒" \
--cron "0 9 * * 1-5" \
--tz "Asia/Shanghai" \
--session isolated \
--message "📢 站会时间到!" \
--deliver \
--channel qqbot \
--to "group:{group_openid}"
```
> 💡 群组使用 `group:{group_openid}` 格式
---
### 场景6查询提醒
**用户**: 我有哪些提醒?
**AI 执行**:
```bash
openclaw cron list
```
**AI 回复**(根据返回结果):
```
📋 你的提醒:
1. ⏰ 喝水提醒 - 3分钟后
2. 🔄 打卡提醒 - 每天08:00
说"取消xx提醒"可删除~
```
---
### 场景7取消提醒
**用户**: 取消打卡提醒
**AI 执行**:
1. 先执行 `openclaw cron list` 找到对应任务 ID
2. 执行 `openclaw cron remove {jobId}`
**AI 回复**:
```
✅ 已取消"打卡提醒"
```
---
## ⚙️ 消息发送说明
### 定时提醒cron add
定时提醒**只能发送主动消息**,因为:
- 提醒执行时,原始 message_id 通常已超过 1 小时有效期
- `openclaw cron add` 命令不支持 `--reply-to` 参数
```
┌─────────────────────┐
│ 定时任务触发 │
└──────────┬──────────┘
┌─────────────────────┐
│ AI 通过 system-event │
│ 获取用户上下文信息 │
└──────────┬──────────┘
┌─────────────────────┐
│ 发送主动消息到用户 │
│ --channel qqbot │
│ --to {openid} │
└──────────┬──────────┘
✅ 用户收到提醒
```
### 即时回复message send
即时消息发送支持被动回复(如果 message_id 有效):
```
┌─────────────────────┐
│ 发送即时消息 │
└──────────┬──────────┘
┌──────────────────────────────┐
│ 有 --reply-to 且 message_id │
│ 在 1 小时内有效? │
└──────────────────────────────┘
↓ ↓
是 否
↓ ↓
┌───────────────┐ ┌─────────────────┐
│ 被动消息回复 │ │ 发送主动消息 │
│ (引用原消息) │ │ (直接发送) │
└───────────────┘ └─────────────────┘
```
---
## ⚠️ 重要限制
| 限制 | 说明 |
|------|------|
| **message_id 有效期** | 1 小时内有效,超时自动降级 |
| **回复次数限制** | 同一 message_id 最多回复 4 次 |
| **主动消息权限** | ⚠️ **QQ 机器人需要申请主动消息权限**,否则定时提醒会发送失败 |
| **主动消息限制** | 只能发给与机器人交互过的用户24小时内 |
| **消息内容** | `--message` 不能为空 |
### ⚠️ 主动消息权限说明
定时提醒功能依赖**主动消息能力**,但 QQ 官方默认**不授予**此权限。
**常见错误**
- 错误码 `40034102`"主动消息失败, 无权限"
- 这表示机器人没有主动消息权限
**解决方案**
1. 登录 [QQ 开放平台](https://q.qq.com/)
2. 进入机器人开发-沙箱管理,消息列表配置中添加自己。
> 💡 **临时替代方案**:在没有主动消息权限前,可以让用户使用"回复"方式获得即时提醒,而非定时提醒。
---
## 📝 消息模板
| 场景 | 触发时输出 | Emoji |
|------|------------|-------|
| 喝水 | 喝水时间到啦! | 💧 🚰 |
| 打卡 | 早上好,打卡时间到! | 🌅 ✅ |
| 会议 | 开会时间到! | 📅 👥 |
| 休息 | 该休息一下了~ | 😴 💤 |
| 日报 | 下班前别忘了写日报哦~ | 📝 ✍️ |
| 运动 | 运动时间到! | 🏃 💪 |
| 吃药 | 该吃药了~ | 💊 🏥 |
| 生日 | 今天是xx的生日 | 🎂 🎉 |
---
## 🔧 用户标识
| 类型 | 格式 | 来源 |
|------|------|------|
| 用户 openid | `B3EA9A1d-2D3c-5CBD-...` | 系统消息自动提供 |
| 群组 openid | `group:FeC1ADaf-...` | 系统消息自动提供 |
| message_id | `ROBOT1.0_xxx` | 系统消息自动提供 |
> 💡 这些信息在系统消息中格式如:
> - `当前用户 openid: B3EA9A1d-...`
> - `当前消息 message_id: ROBOT1.0_...`