mirror of
https://github.com/hansjone/oclaw.git
synced 2026-10-16 06:40:45 +08:00
重构主控编排与运行时预热链路,统一工作区提示词/专家调度协议并补齐 wiki 记忆注入与写回闭环。
同时收敛启动与运维脚本默认行为(含 wiki worker)、更新 Admin 可观测性与相关测试,降低首轮时延并提高运行稳定性。 Made-with: Cursor
This commit is contained in:
parent
4a23b715a2
commit
dbbe3add6a
14438 changed files with 2693620 additions and 2546 deletions
262
openclaw/extensions/qqbot/skills/qqbot-channel/SKILL.md
Normal file
262
openclaw/extensions/qqbot/skills/qqbot-channel/SKILL.md
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
---
|
||||
name: qqbot-channel
|
||||
description: QQ 频道管理技能。查询频道列表、子频道、成员、发帖、公告、日程等操作。使用 qqbot_channel_api 工具代理 QQ 开放平台 HTTP 接口,自动处理 Token 鉴权。当用户需要查看频道、管理子频道、查询成员、发布帖子/公告/日程时使用。
|
||||
metadata: { "openclaw": { "emoji": "📡", "requires": { "config": ["channels.qqbot"] } } }
|
||||
---
|
||||
|
||||
# QQ 频道 API 请求指导
|
||||
|
||||
`qqbot_channel_api` 是一个 QQ 开放平台 HTTP 代理工具,**自动填充鉴权 Token**。你只需要指定 HTTP 方法、API 路径、请求体和查询参数。
|
||||
|
||||
## 📚 详细参考文档
|
||||
|
||||
每个接口的完整参数说明、返回值结构和枚举值定义:
|
||||
|
||||
- `references/api_references.md`
|
||||
|
||||
---
|
||||
|
||||
## 🔧 工具参数
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
| -------- | ------ | ---- | ---------------------------------------------------------------------------- |
|
||||
| `method` | string | 是 | HTTP 方法:`GET`, `POST`, `PUT`, `PATCH`, `DELETE` |
|
||||
| `path` | string | 是 | API 路径(不含域名),如 `/guilds/{guild_id}/channels`,需替换占位符为实际值 |
|
||||
| `body` | object | 否 | 请求体 JSON(POST/PUT/PATCH 使用) |
|
||||
| `query` | object | 否 | URL 查询参数键值对,值为字符串类型 |
|
||||
|
||||
> 基础 URL:`https://api.sgroup.qq.com`,鉴权头 `Authorization: QQBot {token}` 由工具自动填充。
|
||||
|
||||
---
|
||||
|
||||
## ⭐ 接口速查
|
||||
|
||||
### 频道(Guild)
|
||||
|
||||
| 操作 | 方法 | 路径 | 参数说明 |
|
||||
| ----------------- | ----- | ----------------------------------- | ------------------------------------------ |
|
||||
| 获取频道列表 | `GET` | `/users/@me/guilds` | query: `before`, `after`, `limit`(最大100) |
|
||||
| 获取频道 API 权限 | `GET` | `/guilds/{guild_id}/api_permission` | — |
|
||||
|
||||
### 子频道(Channel)
|
||||
|
||||
| 操作 | 方法 | 路径 | 参数说明 |
|
||||
| -------------- | -------- | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| 获取子频道列表 | `GET` | `/guilds/{guild_id}/channels` | — |
|
||||
| 获取子频道详情 | `GET` | `/channels/{channel_id}` | — |
|
||||
| 创建子频道 | `POST` | `/guilds/{guild_id}/channels` | body: `name`\*, `type`\*, `position`\*, `sub_type`, `parent_id`, `private_type`, `private_user_ids`, `speak_permission`, `application_id` |
|
||||
| 修改子频道 | `PATCH` | `/channels/{channel_id}` | body: `name`, `position`, `parent_id`, `private_type`, `speak_permission`(至少一个) |
|
||||
| 删除子频道 | `DELETE` | `/channels/{channel_id}` | ⚠️ 不可逆 |
|
||||
|
||||
**子频道类型(type)**:`0`=文字, `2`=语音, `4`=分组(position≥2), `10005`=直播, `10006`=应用, `10007`=论坛
|
||||
|
||||
### 成员(Member)
|
||||
|
||||
| 操作 | 方法 | 路径 | 参数说明 |
|
||||
| ------------------ | ----- | -------------------------------------------- | --------------------------------------------- |
|
||||
| 获取成员列表 | `GET` | `/guilds/{guild_id}/members` | query: `after`(首次填0), `limit`(1-400) |
|
||||
| 获取成员详情 | `GET` | `/guilds/{guild_id}/members/{user_id}` | — |
|
||||
| 获取身份组成员列表 | `GET` | `/guilds/{guild_id}/roles/{role_id}/members` | query: `start_index`(首次填0), `limit`(1-400) |
|
||||
| 获取在线成员数 | `GET` | `/channels/{channel_id}/online_nums` | — |
|
||||
|
||||
### 公告(Announces)
|
||||
|
||||
| 操作 | 方法 | 路径 | 参数说明 |
|
||||
| -------- | -------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------ |
|
||||
| 创建公告 | `POST` | `/guilds/{guild_id}/announces` | body: `message_id`, `channel_id`, `announces_type`(0=成员,1=欢迎), `recommend_channels`(最多3条) |
|
||||
| 删除公告 | `DELETE` | `/guilds/{guild_id}/announces/{message_id}` | message_id 设 `all` 删除所有 |
|
||||
|
||||
### 论坛(Forum)— 仅私域机器人
|
||||
|
||||
| 操作 | 方法 | 路径 | 参数说明 |
|
||||
| ------------ | -------- | ---------------------------------------------------- | ------------------------------------------------------------------------------ |
|
||||
| 获取帖子列表 | `GET` | `/channels/{channel_id}/threads` | — |
|
||||
| 获取帖子详情 | `GET` | `/channels/{channel_id}/threads/{thread_id}` | — |
|
||||
| 发表帖子 | `PUT` | `/channels/{channel_id}/threads` | body: `title`\*, `content`\*, `format`(1=文本,2=HTML,3=Markdown,4=JSON,默认3) |
|
||||
| 删除帖子 | `DELETE` | `/channels/{channel_id}/threads/{thread_id}` | ⚠️ 不可逆 |
|
||||
| 发表评论 | `POST` | `/channels/{channel_id}/threads/{thread_id}/comment` | body: `thread_author`\*, `content`\*, `thread_create_time`, `image` |
|
||||
|
||||
### 日程(Schedule)
|
||||
|
||||
| 操作 | 方法 | 路径 | 参数说明 |
|
||||
| -------- | -------- | ------------------------------------------------ | ----------------------------------------------------------------------------------------------- |
|
||||
| 创建日程 | `POST` | `/channels/{channel_id}/schedules` | body: `{ schedule: { name*, start_timestamp*, end_timestamp*, jump_channel_id, remind_type } }` |
|
||||
| 修改日程 | `PATCH` | `/channels/{channel_id}/schedules/{schedule_id}` | body: `{ schedule: { name*, start_timestamp*, end_timestamp*, jump_channel_id, remind_type } }` |
|
||||
| 删除日程 | `DELETE` | `/channels/{channel_id}/schedules/{schedule_id}` | ⚠️ 不可逆 |
|
||||
|
||||
**提醒类型(remind_type)**:`"0"`=不提醒, `"1"`=开始时, `"2"`=5分钟前, `"3"`=15分钟前, `"4"`=30分钟前, `"5"`=60分钟前
|
||||
|
||||
> `*` 表示必填参数
|
||||
|
||||
---
|
||||
|
||||
## 💡 调用示例
|
||||
|
||||
### 获取频道列表
|
||||
|
||||
```json
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/users/@me/guilds",
|
||||
"query": { "limit": "100" }
|
||||
}
|
||||
```
|
||||
|
||||
### 获取子频道列表
|
||||
|
||||
```json
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/guilds/123456/channels"
|
||||
}
|
||||
```
|
||||
|
||||
### 创建子频道
|
||||
|
||||
```json
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/guilds/123456/channels",
|
||||
"body": {
|
||||
"name": "新频道",
|
||||
"type": 0,
|
||||
"position": 1,
|
||||
"sub_type": 0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 获取成员列表(分页)
|
||||
|
||||
```json
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/guilds/123456/members",
|
||||
"query": { "after": "0", "limit": "100" }
|
||||
}
|
||||
```
|
||||
|
||||
### 发表论坛帖子
|
||||
|
||||
```json
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "/channels/789012/threads",
|
||||
"body": {
|
||||
"title": "公告标题",
|
||||
"content": "# 标题\n\n公告内容",
|
||||
"format": 3
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 创建日程
|
||||
|
||||
```json
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/channels/456789/schedules",
|
||||
"body": {
|
||||
"schedule": {
|
||||
"name": "周会",
|
||||
"start_timestamp": "1770733800000",
|
||||
"end_timestamp": "1770737400000",
|
||||
"remind_type": "2"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 创建推荐子频道公告
|
||||
|
||||
```json
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/guilds/123456/announces",
|
||||
"body": {
|
||||
"announces_type": 0,
|
||||
"recommend_channels": [{ "channel_id": "789012", "introduce": "欢迎来到攻略频道" }]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 删除所有公告
|
||||
|
||||
```json
|
||||
{
|
||||
"method": "DELETE",
|
||||
"path": "/guilds/123456/announces/all"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 常用操作流程
|
||||
|
||||
### 获取频道和子频道信息
|
||||
|
||||
```
|
||||
1. GET /users/@me/guilds → 获取频道列表,拿到 guild_id
|
||||
2. GET /guilds/{guild_id}/channels → 获取子频道列表,拿到 channel_id
|
||||
3. GET /channels/{channel_id} → 获取子频道详情
|
||||
```
|
||||
|
||||
### 论坛发帖 + 评论
|
||||
|
||||
```
|
||||
1. GET /guilds/{guild_id}/channels → 找到论坛子频道(type=10007)
|
||||
2. PUT /channels/{channel_id}/threads → 发表帖子
|
||||
3. GET /channels/{channel_id}/threads → 获取帖子列表
|
||||
4. GET /channels/{channel_id}/threads/{thread_id} → 获取帖子详情(含 author_id)
|
||||
5. POST /channels/{channel_id}/threads/{thread_id}/comment → 发表评论
|
||||
```
|
||||
|
||||
### 成员管理
|
||||
|
||||
```
|
||||
1. GET /users/@me/guilds → 获取 guild_id
|
||||
2. GET /guilds/{guild_id}/members?after=0&limit=100 → 获取成员列表
|
||||
翻页:用上次最后一个 user.id 作为 after,直到返回空数组
|
||||
3. GET /guilds/{guild_id}/members/{user_id} → 获取指定成员详情
|
||||
```
|
||||
|
||||
### 展示成员头像
|
||||
|
||||
成员详情返回的 `user.avatar` 是头像 URL,**必须使用 Markdown 图片语法展示**,让用户直接看到头像图片,而非纯文本链接:
|
||||
|
||||
```
|
||||
成员信息:
|
||||
· 昵称:{nick}
|
||||
· 头像:
|
||||

|
||||
```
|
||||
|
||||
> **禁止**将头像 URL 作为纯文本或超链接展示(如 `查看头像`),必须用 `` 语法内联显示。频道的 `icon` 字段同理。
|
||||
|
||||
---
|
||||
|
||||
## 🚨 错误码处理
|
||||
|
||||
| 错误码 | 说明 | 解决方案 |
|
||||
| ---------- | ---------------- | ------------------------------------------------------------------------------------- |
|
||||
| **401** | Token 鉴权失败 | 检查 AppID 和 ClientSecret 配置 |
|
||||
| **11241** | 频道 API 无权限 | 前往 QQ 开放平台申请权限,或调用 `GET /guilds/{guild_id}/api_permission` 查看可用权限 |
|
||||
| **11242** | 仅私域机器人可用 | 需在 QQ 开放平台将机器人切换为私域模式 |
|
||||
| **11243** | 需要管理频道权限 | 确保机器人拥有管理权限 |
|
||||
| **11281** | 日程频率限制 | 单管理员/天限 10 次,单频道/天限 100 次 |
|
||||
| **304023** | 推荐子频道超限 | 推荐子频道最多 3 条 |
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 注意事项
|
||||
|
||||
1. **路径中的占位符**(如 `{guild_id}`、`{channel_id}`)必须替换为实际值
|
||||
2. **query 参数的值必须为字符串类型**,如 `{ "limit": "100" }` 而非 `{ "limit": 100 }`
|
||||
3. **成员列表翻页**时可能返回重复成员,需按 `user.id` 去重
|
||||
4. **公告**的两种类型(消息公告和推荐子频道公告)会互相顶替
|
||||
5. **日程**的时间戳为毫秒级字符串
|
||||
6. **删除操作不可逆**,请谨慎使用
|
||||
7. **论坛操作**仅私域机器人可用
|
||||
8. **子频道分组**(type=4)的 `position` 必须 >= 2
|
||||
9. **日程操作**有频率限制:单个管理员每天 10 次,单个频道每天 100 次
|
||||
10. **头像/图标展示**:成员 `user.avatar` 和频道 `icon` 等图片 URL 必须使用 Markdown 图片语法 `` 展示,禁止作为纯文本或超链接展示
|
||||
|
|
@ -0,0 +1,521 @@
|
|||
# QQ 频道 API 完整参考
|
||||
|
||||
本文档包含 QQ 开放平台频道相关所有接口的详细参数说明、返回值结构和枚举值定义。
|
||||
|
||||
通过 `qqbot_channel_api` 工具代理请求,工具自动处理鉴权。
|
||||
|
||||
---
|
||||
|
||||
## 📌 通用说明
|
||||
|
||||
### 基础 URL
|
||||
|
||||
`https://api.sgroup.qq.com`
|
||||
|
||||
### 鉴权(自动处理)
|
||||
|
||||
工具自动填充以下请求头,无需手动设置:
|
||||
|
||||
```
|
||||
Authorization: QQBot {access_token}
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
### 错误返回格式
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "错误描述",
|
||||
"code": 错误码
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📦 返回值类型定义
|
||||
|
||||
### Guild(频道)
|
||||
|
||||
```typescript
|
||||
interface Guild {
|
||||
id: string; // 频道 ID
|
||||
name: string; // 频道名称
|
||||
icon: string; // 频道头像 URL
|
||||
owner_id: string; // 频道拥有者 ID
|
||||
owner: boolean; // 机器人是否为频道拥有者
|
||||
joined_at: string; // 机器人加入时间(ISO 8601)
|
||||
member_count: number; // 频道成员数
|
||||
max_members: number; // 频道最大成员数
|
||||
description: string; // 频道描述
|
||||
}
|
||||
```
|
||||
|
||||
### Channel(子频道)
|
||||
|
||||
```typescript
|
||||
interface Channel {
|
||||
id: string; // 子频道 ID
|
||||
guild_id: string; // 所属频道 ID
|
||||
name: string; // 子频道名称
|
||||
type: number; // 子频道类型(见枚举)
|
||||
position: number; // 排序位置
|
||||
parent_id: string; // 所属分组 ID
|
||||
owner_id: string; // 创建者 ID
|
||||
sub_type: number; // 子类型(见枚举)
|
||||
private_type?: number; // 私密类型(见枚举)
|
||||
speak_permission?: number; // 发言权限(见枚举)
|
||||
application_id?: string; // 应用子频道 AppID
|
||||
}
|
||||
```
|
||||
|
||||
### User(用户)
|
||||
|
||||
```typescript
|
||||
interface User {
|
||||
id: string; // 用户 ID
|
||||
username: string; // 用户名
|
||||
avatar: string; // 头像 URL
|
||||
bot: boolean; // 是否为机器人
|
||||
union_openid?: string; // 特殊关联应用的 openid
|
||||
union_user_account?: string; // 特殊关联应用的用户信息
|
||||
}
|
||||
```
|
||||
|
||||
### Member(成员)
|
||||
|
||||
```typescript
|
||||
interface Member {
|
||||
user: User; // 用户基本信息
|
||||
nick: string; // 在频道中的昵称
|
||||
roles: string[]; // 身份组 ID 列表
|
||||
joined_at: string; // 加入频道时间(ISO 8601)
|
||||
deaf?: boolean; // 是否被禁言
|
||||
mute?: boolean; // 是否被闭麦
|
||||
pending?: boolean; // 是否待审核
|
||||
}
|
||||
```
|
||||
|
||||
### APIPermission(API 权限)
|
||||
|
||||
```typescript
|
||||
interface APIPermission {
|
||||
path: string; // 接口路径
|
||||
method: string; // 请求方法
|
||||
desc: string; // 接口描述
|
||||
auth_status: number; // 授权状态:0=未授权, 1=已授权
|
||||
}
|
||||
```
|
||||
|
||||
### AnnouncesResult(公告结果)
|
||||
|
||||
```typescript
|
||||
interface AnnouncesResult {
|
||||
guild_id: string;
|
||||
channel_id: string;
|
||||
message_id: string;
|
||||
announces_type: number;
|
||||
recommend_channels: RecommendChannel[];
|
||||
}
|
||||
|
||||
interface RecommendChannel {
|
||||
channel_id: string; // 推荐的子频道 ID
|
||||
introduce: string; // 推荐语
|
||||
}
|
||||
```
|
||||
|
||||
### ThreadDetail(帖子详情)
|
||||
|
||||
```typescript
|
||||
interface ThreadDetail {
|
||||
thread: {
|
||||
guild_id: string;
|
||||
channel_id: string;
|
||||
author_id: string;
|
||||
thread_info: {
|
||||
thread_id: string;
|
||||
title: string;
|
||||
content: string;
|
||||
date_time: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### ThreadListResult(帖子列表)
|
||||
|
||||
```typescript
|
||||
interface ThreadListResult {
|
||||
threads: Array<{
|
||||
guild_id: string;
|
||||
channel_id: string;
|
||||
author_id: string;
|
||||
thread_info: {
|
||||
thread_id: string;
|
||||
title: string;
|
||||
content: string;
|
||||
date_time: string;
|
||||
};
|
||||
}>;
|
||||
is_finish: number; // 1=已到底, 0=还有更多
|
||||
}
|
||||
```
|
||||
|
||||
### Schedule(日程)
|
||||
|
||||
```typescript
|
||||
interface Schedule {
|
||||
id?: string;
|
||||
name: string;
|
||||
start_timestamp: string; // 毫秒级时间戳
|
||||
end_timestamp: string;
|
||||
jump_channel_id?: string;
|
||||
remind_type?: string;
|
||||
creator?: {
|
||||
user: { id: string; username: string; bot: boolean };
|
||||
nick: string;
|
||||
joined_at: string;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 枚举值定义
|
||||
|
||||
### 子频道类型(Channel type)
|
||||
|
||||
| 值 | 名称 | 说明 |
|
||||
| ------- | ---------- | -------------------------------- |
|
||||
| `0` | 文字子频道 | 普通文字聊天 |
|
||||
| `2` | 语音子频道 | 语音聊天 |
|
||||
| `4` | 子频道分组 | 组织子频道的分组(position ≥ 2) |
|
||||
| `10005` | 直播子频道 | 直播功能 |
|
||||
| `10006` | 应用子频道 | 需 application_id |
|
||||
| `10007` | 论坛子频道 | 论坛功能 |
|
||||
|
||||
### 子频道子类型(Channel sub_type)
|
||||
|
||||
| 值 | 名称 |
|
||||
| --- | ---- |
|
||||
| `0` | 闲聊 |
|
||||
| `1` | 公告 |
|
||||
| `2` | 攻略 |
|
||||
| `3` | 开黑 |
|
||||
|
||||
### 子频道私密类型(Channel private_type)
|
||||
|
||||
| 值 | 说明 |
|
||||
| --- | -------------------- |
|
||||
| `0` | 公开子频道 |
|
||||
| `1` | 管理员和指定成员可见 |
|
||||
| `2` | 仅管理员可见 |
|
||||
|
||||
### 子频道发言权限(Channel speak_permission)
|
||||
|
||||
| 值 | 说明 |
|
||||
| --- | ------------------------------------------ |
|
||||
| `0` | 无效(仅创建公告子频道时有效,此时为只读) |
|
||||
| `1` | 所有人可发言 |
|
||||
| `2` | 仅管理员和指定成员可发言 |
|
||||
|
||||
### 公告类型(announces_type)
|
||||
|
||||
| 值 | 说明 |
|
||||
| --- | -------- |
|
||||
| `0` | 成员公告 |
|
||||
| `1` | 欢迎公告 |
|
||||
|
||||
### 帖子格式(format)
|
||||
|
||||
| 值 | 格式 |
|
||||
| --- | -------------------- |
|
||||
| `1` | 纯文本 |
|
||||
| `2` | HTML |
|
||||
| `3` | Markdown(**默认**) |
|
||||
| `4` | JSON(RichText) |
|
||||
|
||||
### 日程提醒类型(remind_type)
|
||||
|
||||
| 值 | 说明 |
|
||||
| ----- | -------------- |
|
||||
| `"0"` | 不提醒 |
|
||||
| `"1"` | 开始时提醒 |
|
||||
| `"2"` | 开始前 5 分钟 |
|
||||
| `"3"` | 开始前 15 分钟 |
|
||||
| `"4"` | 开始前 30 分钟 |
|
||||
| `"5"` | 开始前 60 分钟 |
|
||||
|
||||
### API 权限授权状态(auth_status)
|
||||
|
||||
| 值 | 说明 |
|
||||
| --- | ------ |
|
||||
| `0` | 未授权 |
|
||||
| `1` | 已授权 |
|
||||
|
||||
---
|
||||
|
||||
## 📖 各接口详细说明
|
||||
|
||||
### GET /users/@me/guilds — 获取频道列表
|
||||
|
||||
**查询参数**:
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
| -------- | ------ | ---- | ---------------------------------------------------- |
|
||||
| `before` | string | 否 | 读此 guild id 之前的数据 |
|
||||
| `after` | string | 否 | 读此 guild id 之后的数据(与 before 同时设置时无效) |
|
||||
| `limit` | string | 否 | 每次拉取条数,默认 100,最大 100 |
|
||||
|
||||
**返回**: `Guild[]`
|
||||
|
||||
**调用示例**:
|
||||
|
||||
```json
|
||||
{ "method": "GET", "path": "/users/@me/guilds", "query": { "limit": "100" } }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### GET /guilds/{guild_id}/api_permission — 获取频道 API 权限
|
||||
|
||||
**返回**: `{ apis: APIPermission[] }`
|
||||
|
||||
**调用示例**:
|
||||
|
||||
```json
|
||||
{ "method": "GET", "path": "/guilds/123456/api_permission" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### GET /guilds/{guild_id}/channels — 获取子频道列表
|
||||
|
||||
**返回**: `Channel[]`
|
||||
|
||||
**调用示例**:
|
||||
|
||||
```json
|
||||
{ "method": "GET", "path": "/guilds/123456/channels" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### GET /channels/{channel_id} — 获取子频道详情
|
||||
|
||||
**返回**: `Channel`
|
||||
|
||||
---
|
||||
|
||||
### POST /guilds/{guild_id}/channels — 创建子频道
|
||||
|
||||
> ⚠️ 仅私域机器人可用,需管理频道权限
|
||||
|
||||
**请求体**:
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
| ------------------ | -------- | ---- | ------------------------------------- |
|
||||
| `name` | string | 是 | 子频道名称 |
|
||||
| `type` | number | 是 | 子频道类型 |
|
||||
| `position` | number | 是 | 排序位置(type=4 时 ≥ 2) |
|
||||
| `sub_type` | number | 否 | 子类型 |
|
||||
| `parent_id` | string | 否 | 所属分组 ID |
|
||||
| `private_type` | number | 否 | 私密类型 |
|
||||
| `private_user_ids` | string[] | 否 | 私密成员列表(private_type=1 时有效) |
|
||||
| `speak_permission` | number | 否 | 发言权限 |
|
||||
| `application_id` | string | 否 | 应用 AppID(type=10006 时需要) |
|
||||
|
||||
**返回**: `Channel`
|
||||
|
||||
---
|
||||
|
||||
### PATCH /channels/{channel_id} — 修改子频道
|
||||
|
||||
> ⚠️ 仅私域机器人可用
|
||||
|
||||
**请求体**(至少一个):
|
||||
|
||||
| 参数 | 类型 | 说明 |
|
||||
| ------------------ | ------ | -------- |
|
||||
| `name` | string | 名称 |
|
||||
| `position` | number | 排序位置 |
|
||||
| `parent_id` | string | 分组 ID |
|
||||
| `private_type` | number | 私密类型 |
|
||||
| `speak_permission` | number | 发言权限 |
|
||||
|
||||
**返回**: `Channel`
|
||||
|
||||
---
|
||||
|
||||
### DELETE /channels/{channel_id} — 删除子频道
|
||||
|
||||
> ⚠️ 不可逆!仅私域机器人可用
|
||||
|
||||
---
|
||||
|
||||
### GET /guilds/{guild_id}/members — 获取成员列表
|
||||
|
||||
> 仅私域机器人可用
|
||||
|
||||
**查询参数**:
|
||||
|
||||
| 参数 | 类型 | 说明 |
|
||||
| ------- | ------ | ---------------------------------- |
|
||||
| `after` | string | 上次最后一个 user.id,首次填 `"0"` |
|
||||
| `limit` | string | 分页大小 1-400,默认 1 |
|
||||
|
||||
**返回**: `Member[]`
|
||||
|
||||
> 翻页:用最后一个 `user.id` 作为 `after`,直到返回空数组。可能返回重复成员,需按 `user.id` 去重。
|
||||
|
||||
---
|
||||
|
||||
### GET /guilds/{guild_id}/members/{user_id} — 获取成员详情
|
||||
|
||||
**返回**: `Member`
|
||||
|
||||
---
|
||||
|
||||
### GET /guilds/{guild_id}/roles/{role_id}/members — 获取身份组成员列表
|
||||
|
||||
> 仅私域机器人可用
|
||||
|
||||
**查询参数**:
|
||||
|
||||
| 参数 | 类型 | 说明 |
|
||||
| ------------- | ------ | ---------------------- |
|
||||
| `start_index` | string | 分页标识,首次填 `"0"` |
|
||||
| `limit` | string | 分页大小 1-400,默认 1 |
|
||||
|
||||
**返回**: `{ data: Member[], next: string }`
|
||||
|
||||
> 翻页:用 `next` 作为 `start_index`,直到 `data` 为空。
|
||||
|
||||
---
|
||||
|
||||
### GET /channels/{channel_id}/online_nums — 获取在线成员数
|
||||
|
||||
**返回**: `{ online_nums: number }`
|
||||
|
||||
---
|
||||
|
||||
### POST /guilds/{guild_id}/announces — 创建频道公告
|
||||
|
||||
**请求体**:
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
| -------------------- | ------ | ---- | --------------------------------------------------- |
|
||||
| `message_id` | string | 否 | 消息 ID(有值时创建消息公告,此时 channel_id 必填) |
|
||||
| `channel_id` | string | 否 | 子频道 ID |
|
||||
| `announces_type` | number | 否 | 0=成员公告,1=欢迎公告 |
|
||||
| `recommend_channels` | array | 否 | 推荐子频道列表(最多 3 条,message_id 为空时生效) |
|
||||
|
||||
> 两种公告类型会互相顶替
|
||||
|
||||
**返回**: `AnnouncesResult`
|
||||
|
||||
---
|
||||
|
||||
### DELETE /guilds/{guild_id}/announces/{message_id} — 删除公告
|
||||
|
||||
> `message_id` 设为 `all` 删除所有公告
|
||||
|
||||
---
|
||||
|
||||
### GET /channels/{channel_id}/threads — 获取帖子列表
|
||||
|
||||
> 仅私域机器人可用,channel_id 须为论坛子频道(type=10007)
|
||||
|
||||
**返回**: `ThreadListResult`
|
||||
|
||||
---
|
||||
|
||||
### GET /channels/{channel_id}/threads/{thread_id} — 获取帖子详情
|
||||
|
||||
> 仅私域机器人可用
|
||||
|
||||
**返回**: `ThreadDetail`
|
||||
|
||||
---
|
||||
|
||||
### PUT /channels/{channel_id}/threads — 发表帖子
|
||||
|
||||
> 仅私域机器人可用
|
||||
|
||||
**请求体**:
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
| --------- | ------ | ---- | ------------------------------------------ |
|
||||
| `title` | string | 是 | 帖子标题 |
|
||||
| `content` | string | 是 | 帖子内容 |
|
||||
| `format` | number | 否 | 1=文本, 2=HTML, 3=Markdown(默认), 4=JSON |
|
||||
|
||||
**返回**: `{ task_id: string, create_time: string }`
|
||||
|
||||
---
|
||||
|
||||
### DELETE /channels/{channel_id}/threads/{thread_id} — 删除帖子
|
||||
|
||||
> ⚠️ 不可逆!仅私域机器人可用
|
||||
|
||||
---
|
||||
|
||||
### POST /channels/{channel_id}/threads/{thread_id}/comment — 发表评论
|
||||
|
||||
> 仅私域机器人可用
|
||||
|
||||
**请求体**:
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
| -------------------- | ------ | ---- | ------------ |
|
||||
| `thread_author` | string | 是 | 帖子作者 ID |
|
||||
| `content` | string | 是 | 评论内容 |
|
||||
| `thread_create_time` | string | 否 | 帖子创建时间 |
|
||||
| `image` | string | 否 | 图片链接 |
|
||||
|
||||
**返回**: `{ task_id: string, create_time: number }`
|
||||
|
||||
---
|
||||
|
||||
### POST /channels/{channel_id}/schedules — 创建日程
|
||||
|
||||
> 需要管理频道权限。单管理员/天限 10 次,单频道/天限 100 次。
|
||||
|
||||
**请求体**:
|
||||
|
||||
```json
|
||||
{
|
||||
"schedule": {
|
||||
"name": "日程名称",
|
||||
"start_timestamp": "毫秒时间戳",
|
||||
"end_timestamp": "毫秒时间戳",
|
||||
"jump_channel_id": "0",
|
||||
"remind_type": "0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
| -------------------------- | ------ | ---- | ------------------------- |
|
||||
| `schedule.name` | string | 是 | 日程名称 |
|
||||
| `schedule.start_timestamp` | string | 是 | 开始时间(毫秒) |
|
||||
| `schedule.end_timestamp` | string | 是 | 结束时间(毫秒) |
|
||||
| `schedule.jump_channel_id` | string | 否 | 跳转子频道 ID,默认 `"0"` |
|
||||
| `schedule.remind_type` | string | 否 | 提醒类型,默认 `"0"` |
|
||||
|
||||
**返回**: `Schedule`
|
||||
|
||||
---
|
||||
|
||||
### PATCH /channels/{channel_id}/schedules/{schedule_id} — 修改日程
|
||||
|
||||
> 需要管理频道权限
|
||||
|
||||
**请求体**:同创建日程
|
||||
|
||||
**返回**: `Schedule`
|
||||
|
||||
---
|
||||
|
||||
### DELETE /channels/{channel_id}/schedules/{schedule_id} — 删除日程
|
||||
|
||||
> ⚠️ 不可逆!需要管理频道权限
|
||||
36
openclaw/extensions/qqbot/skills/qqbot-media/SKILL.md
Normal file
36
openclaw/extensions/qqbot/skills/qqbot-media/SKILL.md
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
---
|
||||
name: qqbot-media
|
||||
description: QQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
|
||||
metadata: { "openclaw": { "emoji": "📸", "requires": { "config": ["channels.qqbot"] } } }
|
||||
---
|
||||
|
||||
# QQBot 富媒体收发
|
||||
|
||||
## 用法
|
||||
|
||||
```
|
||||
<qqmedia>路径或URL</qqmedia>
|
||||
```
|
||||
|
||||
系统根据文件扩展名自动识别类型并路由:
|
||||
|
||||
- `.jpg/.png/.gif/.webp/.bmp` → 图片
|
||||
- `.silk/.wav/.mp3/.ogg/.aac/.flac` 等 → 语音
|
||||
- `.mp4/.mov/.avi/.mkv/.webm` 等 → 视频
|
||||
- 其他扩展名 → 文件
|
||||
- 无扩展名的 URL → 默认按图片处理
|
||||
|
||||
## 接收媒体
|
||||
|
||||
- 用户发来的**图片**自动下载到本地,路径在上下文【附件】中,可直接用 `<qqmedia>路径</qqmedia>` 回发
|
||||
- 用户发来的**语音**路径在上下文中;若有 STT 能力则优先转写
|
||||
|
||||
## 规则
|
||||
|
||||
1. **路径必须是绝对路径**(以 `/` 或 `http` 开头)
|
||||
2. **标签必须用开闭标签包裹路径**:`<qqmedia>路径</qqmedia>`
|
||||
3. **文件大小上限 10MB**
|
||||
4. **你有能力发送本地图片/文件**,直接用标签包裹路径即可,**不要说"无法发送"**
|
||||
5. 发送语音时不要重复语音中已朗读的文字
|
||||
6. 多个媒体用多个标签
|
||||
7. 以会话上下文中的能力说明为准(如未启用语音则不要发语音)
|
||||
149
openclaw/extensions/qqbot/skills/qqbot-remind/SKILL.md
Normal file
149
openclaw/extensions/qqbot/skills/qqbot-remind/SKILL.md
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
---
|
||||
name: qqbot-remind
|
||||
description: QQBot 定时提醒。支持一次性和周期性提醒的创建、查询、取消。当通过 QQ 通道通信且涉及提醒/定时任务时使用。
|
||||
metadata: { "openclaw": { "emoji": "⏰", "requires": { "config": ["channels.qqbot"] } } }
|
||||
---
|
||||
|
||||
# QQ Bot 定时提醒
|
||||
|
||||
## ⚠️ 强制规则
|
||||
|
||||
**当用户提到「提醒」「闹钟」「定时」「X分钟/小时后」「每天X点」「叫我」等任何涉及延时或定时的请求时,你必须调用工具,绝对不能只用自然语言回复说"好的,我会提醒你"!**
|
||||
|
||||
你没有内存或后台线程,口头承诺"到时候提醒"是无效的——只有调用工具才能真正注册定时任务。
|
||||
|
||||
---
|
||||
|
||||
## 推荐流程(优先使用 `qqbot_remind` 工具)
|
||||
|
||||
**第一步**:调用 `qqbot_remind` 工具,传入简单参数:
|
||||
|
||||
| 参数 | 说明 | 示例 |
|
||||
| --------- | -------------------------------------------- | ---------------------------------- |
|
||||
| `action` | 操作类型 | `"add"` / `"list"` / `"remove"` |
|
||||
| `content` | 提醒内容 | `"喝水"` |
|
||||
| `to` | 目标地址(可选,系统自动获取,通常无需填写) | — |
|
||||
| `time` | 时间(相对时间或 cron 表达式) | `"5m"` / `"1h30m"` / `"0 8 * * *"` |
|
||||
| `jobId` | 任务 ID(仅 remove) | `"xxx"` |
|
||||
|
||||
**第二步**:`qqbot_remind` 会返回 `cronParams`,你必须**立即**将 `cronParams` 的值作为参数调用 `cron` 工具。
|
||||
|
||||
**第三步**:根据 `cron` 工具的返回结果,回复用户。
|
||||
|
||||
### 示例
|
||||
|
||||
用户说:"5分钟后提醒我喝水"
|
||||
|
||||
1. 调用 `qqbot_remind`:`{ "action": "add", "content": "喝水", "time": "5m" }`
|
||||
2. 收到返回的 `cronParams` → 立即调用 `cron` 工具,参数为该 `cronParams`
|
||||
3. 回复用户:`⏰ 好的,5分钟后提醒你喝水~`
|
||||
|
||||
---
|
||||
|
||||
## 备用方案(直接使用 `cron` 工具)
|
||||
|
||||
> 仅当 `qqbot_remind` 工具不可用时使用以下方式。
|
||||
|
||||
### 核心规则
|
||||
|
||||
> **payload.kind 必须是 `"agentTurn"`,绝对不能用 `"systemEvent"`!**
|
||||
> `systemEvent` 只在 AI 会话内部注入文本,用户收不到 QQ 消息。
|
||||
|
||||
**5 个不可更改字段**:
|
||||
|
||||
| 字段 | 固定值 | 原因 |
|
||||
| ----------------- | ------------- | ---------------------------- |
|
||||
| `payload.kind` | `"agentTurn"` | `systemEvent` 不会发 QQ 消息 |
|
||||
| `payload.deliver` | `true` | 否则不投递 |
|
||||
| `payload.channel` | `"qqbot"` | QQ 通道标识 |
|
||||
| `payload.to` | 用户 openid | 从 `To` 字段获取 |
|
||||
| `sessionTarget` | `"isolated"` | 隔离会话避免污染 |
|
||||
|
||||
> `schedule.atMs` 必须是**绝对毫秒时间戳**(如 `1770733800000`),不支持 `"5m"` 等相对字符串。
|
||||
> 计算方式:`当前时间戳ms + 延迟毫秒`。
|
||||
|
||||
### 一次性提醒(schedule.kind = "at")
|
||||
|
||||
```json
|
||||
{
|
||||
"action": "add",
|
||||
"job": {
|
||||
"name": "{任务名}",
|
||||
"schedule": { "kind": "at", "atMs": "{当前时间戳ms + N*60000}" },
|
||||
"sessionTarget": "isolated",
|
||||
"wakeMode": "now",
|
||||
"deleteAfterRun": true,
|
||||
"payload": {
|
||||
"kind": "agentTurn",
|
||||
"message": "你是一个暖心的提醒助手。请用温暖、有趣的方式提醒用户:{提醒内容}。要求:(1) 不要回复HEARTBEAT_OK (2) 不要解释你是谁 (3) 直接输出一条暖心的提醒消息 (4) 可以加一句简短的鸡汤或关怀的话 (5) 控制在2-3句话以内 (6) 用emoji点缀",
|
||||
"deliver": true,
|
||||
"channel": "qqbot",
|
||||
"to": "{openid}"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 周期提醒(schedule.kind = "cron")
|
||||
|
||||
```json
|
||||
{
|
||||
"action": "add",
|
||||
"job": {
|
||||
"name": "{任务名}",
|
||||
"schedule": { "kind": "cron", "expr": "0 8 * * *", "tz": "Asia/Shanghai" },
|
||||
"sessionTarget": "isolated",
|
||||
"wakeMode": "now",
|
||||
"payload": {
|
||||
"kind": "agentTurn",
|
||||
"message": "你是一个暖心的提醒助手。请用温暖、有趣的方式提醒用户:{提醒内容}。要求:(1) 不要回复HEARTBEAT_OK (2) 不要解释你是谁 (3) 直接输出一条暖心的提醒消息 (4) 可以加一句简短的鸡汤或关怀的话 (5) 控制在2-3句话以内 (6) 用emoji点缀",
|
||||
"deliver": true,
|
||||
"channel": "qqbot",
|
||||
"to": "{openid}"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> 周期任务**不加** `deleteAfterRun`。群聊 `to` 格式为 `"group:{group_openid}"`。
|
||||
|
||||
---
|
||||
|
||||
## cron 表达式速查
|
||||
|
||||
| 场景 | expr |
|
||||
| -------------- | ---------------- |
|
||||
| 每天早上8点 | `"0 8 * * *"` |
|
||||
| 每天晚上10点 | `"0 22 * * *"` |
|
||||
| 工作日早上9点 | `"0 9 * * 1-5"` |
|
||||
| 每周一早上9点 | `"0 9 * * 1"` |
|
||||
| 每周末上午10点 | `"0 10 * * 0,6"` |
|
||||
| 每小时整点 | `"0 * * * *"` |
|
||||
|
||||
> 周期提醒必须加 `"tz": "Asia/Shanghai"`。
|
||||
|
||||
---
|
||||
|
||||
## AI 决策指南
|
||||
|
||||
| 用户说法 | action | time 格式 |
|
||||
| ------------------- | ---------------- | --------------- |
|
||||
| "5分钟后提醒我喝水" | `add` | `"5m"` |
|
||||
| "1小时后提醒开会" | `add` | `"1h"` |
|
||||
| "每天8点提醒我打卡" | `add` | `"0 8 * * *"` |
|
||||
| "工作日早上9点提醒" | `add` | `"0 9 * * 1-5"` |
|
||||
| "我有哪些提醒" | `list` | — |
|
||||
| "取消喝水提醒" | `remove` | — |
|
||||
| "修改提醒时间" | `remove` → `add` | — |
|
||||
| "提醒我"(无时间) | **需追问** | — |
|
||||
|
||||
纯相对时间("5分钟后"、"1小时后")可直接计算,无需确认。时间模糊或缺失时需追问。
|
||||
|
||||
---
|
||||
|
||||
## 回复模板
|
||||
|
||||
- 一次性:`⏰ 好的,{时间}后提醒你{内容}~`
|
||||
- 周期:`⏰ 收到,{周期}提醒你{内容}~`
|
||||
- 查询无结果:`📋 目前没有提醒哦~ 说"5分钟后提醒我xxx"试试?`
|
||||
- 删除成功:`✅ 已取消"{名称}"`
|
||||
Loading…
Add table
Add a link
Reference in a new issue