From 9d266027619ef703dd5b182224592b76c3333ab2 Mon Sep 17 00:00:00 2001 From: Richard Chien Date: Mon, 30 Dec 2019 09:46:33 +0800 Subject: [PATCH] Update docs for v4.13.0 --- docs/4.13/API.md | 866 ++++++++++++++++++++++++++++++ docs/4.13/CQCode.md | 77 +++ docs/4.13/CommunicationMethods.md | 121 +++++ docs/4.13/Configuration.md | 193 +++++++ docs/4.13/Docker.md | 44 ++ docs/4.13/EventFilter.md | 133 +++++ docs/4.13/Extension.md | 13 + docs/4.13/Home.md | 56 ++ docs/4.13/Message.md | 123 +++++ docs/4.13/Post.md | 413 ++++++++++++++ docs/4.13/UpgradeGuide.md | 42 ++ docs/4.13/WebSocketAPI.md | 72 +++ docs/4.13/config.js | 64 +++ docs/4.13/index.html | 22 + docs/index.html | 2 +- docs/init.js | 1 + 16 files changed, 2241 insertions(+), 1 deletion(-) create mode 100644 docs/4.13/API.md create mode 100644 docs/4.13/CQCode.md create mode 100644 docs/4.13/CommunicationMethods.md create mode 100644 docs/4.13/Configuration.md create mode 100644 docs/4.13/Docker.md create mode 100644 docs/4.13/EventFilter.md create mode 100644 docs/4.13/Extension.md create mode 100644 docs/4.13/Home.md create mode 100644 docs/4.13/Message.md create mode 100644 docs/4.13/Post.md create mode 100644 docs/4.13/UpgradeGuide.md create mode 100644 docs/4.13/WebSocketAPI.md create mode 100644 docs/4.13/config.js create mode 100644 docs/4.13/index.html diff --git a/docs/4.13/API.md b/docs/4.13/API.md new file mode 100644 index 0000000..8282ec3 --- /dev/null +++ b/docs/4.13/API.md @@ -0,0 +1,866 @@ +# API 描述 + +## 请求方式 + +所有 API 都同时支持 GET 和 POST 两种请求方式(除获取 `data` 目录中的文件),参数可通过 URL 参数、表单或 JSON 传入,后两者分别对应 Content-Type `application/x-www-form-urlencoded` 和 `application/json`。如果使用 JSON 传入,参数要放在根级别的 JSON 对象中,且参数的数据类型必须符合 API 列表中给出的每个参数所要求的数据类型,大致如下: + +```json +{"user_id": 123456, "message": "hello"} +``` + +**为避免各种可能的问题,建议使用 JSON 方式传入。** + +API 描述中没有给出默认值的参数均为必填项。 + +如果配置文件中填写了 `access_token`,则每次请求需要在请求头中加入验证头,如: + +```http +GET /send_private_msg?user_id=123456&message=hello HTTP/1.1 +Authorization: Bearer kSLuTF2GC2Q4q4ugm3 +``` + +`kSLuTF2GC2Q4q4ugm3` 换成你填写的 access token。 + +Access token 也可以通过 query 参数 `access_token` 传入,以便在无法修改请求头的情况下使用,例如: + +```http +GET /send_private_msg?access_token=kSLuTF2GC2Q4q4ugm3&user_id=123456&message=hello HTTP/1.1 +``` + +## 响应说明 + +对于任何请求: + +- 如果 access token 未提供,状态码为 401; +- 如果 access token 不符合,状态码为 403; +- 如果 POST 请求的 Content-Type 不支持,状态码为 406; +- 如果 POST 请求的正文格式不正确,状态码为 400; +- 如果 API 不存在,状态码为 404; +- 剩下的所有情况,无论操作失败还是成功,状态码都是 200。 + +响应内容为 JSON 格式,基本结构如下: + +```json +{ + "status": "ok", + "retcode": 0, + "data": { + "id": 123456, + "nickname": "滑稽" + } +} +``` + +`status` 字段如果是 `ok` 则表示操作成功,同时 `retcode` (返回码)会等于 0,即 酷Q 函数返回了 0。 + +`status` 字段如果是 `async` 则表示请求已提交异步处理,此时 `retcode` 为 1,具体成功或失败将无法获知。 + +`status` 字段如果是 `failed` 则表示操作失败,此时 `retcode` 有两种情况:当大于 0 时,表示是 HTTP API 插件判断出的失败;小于 0 时,为调用 酷Q 函数的返回码,具体含义直接参考 酷Q 文档的 [错误代码](https://docs.cqp.im/dev/v9/errorcode/) 和 酷Q 日志。 + +汇总如下: + +| `retcode` | 说明 | +| --------- | ---- | +| 0 | 同时 `status` 为 `ok`,表示操作成功 | +| 1 | 同时 `status` 为 `async`,表示操作已进入异步执行,具体结果未知 | +| 100 | 参数缺失或参数无效,通常是因为没有传入必要参数,某些接口中也可能因为参数明显无效(比如传入的 QQ 号小于等于 0,此时无需调用 酷Q 函数即可确定失败),此项和以下的 `status` 均为 `failed` | +| 102 | 酷Q 函数返回的数据无效,一般是因为传入参数有效但没有权限,比如试图获取没有加入的群组的成员列表 | +| 103 | 操作失败,一般是因为用户权限不足,或文件系统异常、不符合预期 | +| 104 | 由于 酷Q 提供的凭证(Cookie 和 CSRF Token)失效导致请求 QQ 相关接口失败,可尝试清除 酷Q 缓存来解决 | +| 201 | 工作线程池未正确初始化(无法执行异步任务) | + +`data` 字段为 API 返回数据的内容,对于踢人、禁言等不需要返回数据的操作,这里为 null,对于获取群成员信息这类操作,这里为所获取的数据的对象,具体的数据内容将会在相应的 API 描述中给出。注意,异步版本的 API,`data` 永远是 null,即使其相应的同步接口本身是有数据。 + +后面的 API 描述中将只给出 `data` 字段的内容,放在「响应数据」标题下。 + +## 参数中的数据类型 + +在描述 API 的参数时,「数据类型」使用 JSON 中的名字,例如 `string`、`number` 等。 + +特别地,数据类型 `message` 表示该参数是一个消息类型的参数,在调用 API 时,`message` 类型的参数允许接受字符串、消息段数组、单个消息段对象三种类型的数据,关于消息格式的更多细节请查看 [消息格式](/Message)。 + +## 异步调用 + +下面列出的**所有** API 都可以通过附加后缀 `_async` 来进行异步调用,例如 `/send_private_msg_async`、`/send_msg_async`、`/clean_data_dir_async`。 + +异步调用的响应中,`status` 字段为 `async`。 + +需要注意的是,虽然说以 `get_` 开头的那些接口也可以进行异步调用,但实际上客户端没有办法得知最终的调用结果,所以对这部分接口进行异步调用是没有意义的;另外,有一些接口本身就是异步执行的(返回的 `status` 为 `async`),此时使用 `_async` 后缀来调用不会产生本质上的区别。 + +## 限速调用 + +将配置项 `enable_rate_limited_actions` 设置为 `true` 可开启限速调用支持(默认为 `false`)。 + +下面列出的**所有** API 都可以通过附加后缀 `_rate_limited` 来进行限速调用,例如 `/send_private_msg_rate_limited`、`/send_msg_rate_limited`,不过主要还是用在发送消息接口上,以避免消息频率过快导致腾讯封号。所有限速调用将会以指定速度**排队执行**,这个速度由配置项 `rate_limit_interval` 来控制,单位毫秒,默认 500。 + +限速调用的响应中,`status` 字段为 `async`。 + +## API 列表 + +### `/send_private_msg` 发送私聊消息 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `user_id` | number | - | 对方 QQ 号 | +| `message` | message | - | 要发送的内容 | +| `auto_escape` | boolean | `false` | 消息内容是否作为纯文本发送(即不解析 CQ 码),只在 `message` 字段是字符串时有效 | + +#### 响应数据 + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `message_id` | number (int32) | 消息 ID | + +### `/send_group_msg` 发送群消息 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `group_id` | number | - | 群号 | +| `message` | message | - | 要发送的内容 | +| `auto_escape` | boolean | `false` | 消息内容是否作为纯文本发送(即不解析 CQ 码),只在 `message` 字段是字符串时有效 | + +#### 响应数据 + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `message_id` | number (int32) | 消息 ID | + +### `/send_discuss_msg` 发送讨论组消息 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `discuss_id` | number | - | 讨论组 ID(正常情况下看不到,需要从讨论组消息上报的数据中获得) | +| `message` | message | - | 要发送的内容 | +| `auto_escape` | boolean | `false` | 消息内容是否作为纯文本发送(即不解析 CQ 码),只在 `message` 字段是字符串时有效 | + +#### 响应数据 + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `message_id` | number (int32) | 消息 ID | + +### `/send_msg` 发送消息 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `message_type` | string | - | 消息类型,支持 `private`、`group`、`discuss`,分别对应私聊、群组、讨论组,如不传入,则根据传入的 `*_id` 参数判断 | +| `user_id` | number | - | 对方 QQ 号(消息类型为 `private` 时需要) | +| `group_id` | number | - | 群号(消息类型为 `group` 时需要) | +| `discuss_id` | number | - | 讨论组 ID(消息类型为 `discuss` 时需要) | +| `message` | message | - | 要发送的内容 | +| `auto_escape` | boolean | `false` | 消息内容是否作为纯文本发送(即不解析 CQ 码),只在 `message` 字段是字符串时有效 | + +#### 响应数据 + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `message_id` | number (int32) | 消息 ID | + +### `/delete_msg` 撤回消息 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `message_id` | number (int32) | - | 消息 ID | + +#### 响应数据 + +无 + +### `/send_like` 发送好友赞 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `user_id` | number | - | 对方 QQ 号 | +| `times` | number | 1 | 赞的次数,每个好友每天最多 10 次 | + +#### 响应数据 + +无 + +### `/set_group_kick` 群组踢人 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `group_id` | number | - | 群号 | +| `user_id` | number | - | 要踢的 QQ 号 | +| `reject_add_request` | boolean | `false` | 拒绝此人的加群请求 | + +#### 响应数据 + +无 + +### `/set_group_ban` 群组单人禁言 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `group_id` | number | - | 群号 | +| `user_id` | number | - | 要禁言的 QQ 号 | +| `duration` | number | `30 * 60` | 禁言时长,单位秒,0 表示取消禁言 | + +#### 响应数据 + +无 + +### `/set_group_anonymous_ban` 群组匿名用户禁言 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `group_id` | number | - | 群号 | +| `anonymous` | object | - | 可选,要禁言的匿名用户对象(群消息上报的 `anonymous` 字段) | +| `anonymous_flag` 或 `flag` | string | - | 可选,要禁言的匿名用户的 flag(需从群消息上报的数据中获得) | +| `duration` | number | `30 * 60` | 禁言时长,单位秒,无法取消匿名用户禁言 | + +上面的 `anonymous` 和 `anonymous_flag` 两者任选其一传入即可,若都传入,则使用 `anonymous`。 + +#### 响应数据 + +无 + +### `/set_group_whole_ban` 群组全员禁言 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `group_id` | number | - | 群号 | +| `enable` | boolean | `true` | 是否禁言 | + +#### 响应数据 + +无 + +### `/set_group_admin` 群组设置管理员 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `group_id` | number | - | 群号 | +| `user_id` | number | - | 要设置管理员的 QQ 号 | +| `enable` | boolean | `true` | true 为设置,false 为取消 | + +#### 响应数据 + +无 + +### `/set_group_anonymous` 群组匿名 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `group_id` | number | - | 群号 | +| `enable` | boolean | `true` | 是否允许匿名聊天 | + +#### 响应数据 + +无 + +### `/set_group_card` 设置群名片(群备注) + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `group_id` | number | - | 群号 | +| `user_id` | number | - | 要设置的 QQ 号 | +| `card` | string | 空 | 群名片内容,不填或空字符串表示删除群名片 | + +#### 响应数据 + +无 + +### `/set_group_leave` 退出群组 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `group_id` | number | - | 群号 | +| `is_dismiss` | boolean | `false` | 是否解散,如果登录号是群主,则仅在此项为 true 时能够解散 | + +#### 响应数据 + +无 + +### `/set_group_special_title` 设置群组专属头衔 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `group_id` | number | - | 群号 | +| `user_id` | number | - | 要设置的 QQ 号 | +| `special_title` | string | 空 | 专属头衔,不填或空字符串表示删除专属头衔 | +| `duration` | number | `-1` | 专属头衔有效期,单位秒,-1 表示永久,不过此项似乎没有效果,可能是只有某些特殊的时间长度有效,有待测试 | + +#### 响应数据 + +无 + +### `/set_discuss_leave` 退出讨论组 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `discuss_id` | number | - | 讨论组 ID(正常情况下看不到,需要从讨论组消息上报的数据中获得) | + +#### 响应数据 + +无 + +### `/set_friend_add_request` 处理加好友请求 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `flag` | string | - | 加好友请求的 flag(需从上报的数据中获得) | +| `approve` | boolean | `true` | 是否同意请求 | +| `remark` | string | 空 | 添加后的好友备注(仅在同意时有效) | + +#### 响应数据 + +无 + +### `/set_group_add_request` 处理加群请求/邀请 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `flag` | string | - | 加群请求的 flag(需从上报的数据中获得) | +| `sub_type` 或 `type` | string | - | `add` 或 `invite`,请求类型(需要和上报消息中的 `sub_type` 字段相符) | +| `approve` | boolean | `true` | 是否同意请求/邀请 | +| `reason` | string | 空 | 拒绝理由(仅在拒绝时有效) | + +#### 响应数据 + +无 + +### `/get_login_info` 获取登录号信息 + +#### 参数 + +无 + +#### 响应数据 + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `user_id` | number (int64) | QQ 号 | +| `nickname` | string | QQ 昵称 | + +### `/get_stranger_info` 获取陌生人信息 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `user_id` | number | - | QQ 号 | +| `no_cache` | boolean | `false` | 是否不使用缓存(使用缓存可能更新不及时,但响应更快) | + +#### 响应数据 + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `user_id` | number (int64) | QQ 号 | +| `nickname` | string | 昵称 | +| `sex` | string | 性别,`male` 或 `female` 或 `unknown` | +| `age` | number (int32) | 年龄 | + +### `/get_friend_list` 获取好友列表 + +#### 参数 + +无 + +#### 响应数据 + +响应内容为 JSON 数组,每个元素如下: + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `user_id` | number (int64) | QQ 号 | +| `nickname` | string | 昵称 | +| `remark` | string | 备注名 | + +### `/get_group_list` 获取群列表 + +#### 参数 + +无 + +#### 响应数据 + +响应内容为 JSON 数组,每个元素如下: + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `group_id` | number (int64) | 群号 | +| `group_name` | string | 群名称 | + +### `/get_group_info` 获取群信息 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `group_id` | number | - | 群号 | +| `no_cache` | boolean | `false` | 是否不使用缓存(使用缓存可能更新不及时,但响应更快) | + +#### 响应数据 + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `group_id` | number (int64) | 群号 | +| `group_name` | string | 群名称 | +| `member_count` | number (int32) | 成员数 | +| `max_member_count` | number (int32) | 最大成员数(群容量) | + +### `/get_group_member_info` 获取群成员信息 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `group_id` | number | - | 群号 | +| `user_id` | number | - | QQ 号 | +| `no_cache` | boolean | `false` | 是否不使用缓存(使用缓存可能更新不及时,但响应更快) | + +#### 响应数据 + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `group_id` | number (int64) | 群号 | +| `user_id` | number (int64) | QQ 号 | +| `nickname` | string | 昵称 | +| `card` | string | 群名片/备注 | +| `sex` | string | 性别,`male` 或 `female` 或 `unknown` | +| `age` | number (int32) | 年龄 | +| `area` | string | 地区 | +| `join_time` | number (int32) | 加群时间戳 | +| `last_sent_time` | number (int32) | 最后发言时间戳 | +| `level` | string | 成员等级 | +| `role` | string | 角色,`owner` 或 `admin` 或 `member` | +| `unfriendly` | boolean | 是否不良记录成员 | +| `title` | string | 专属头衔 | +| `title_expire_time` | number (int32) | 专属头衔过期时间戳 | +| `card_changeable` | boolean | 是否允许修改群名片 | + +### `/get_group_member_list` 获取群成员列表 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `group_id` | number | - | 群号 | + +#### 响应数据 + +响应内容为 JSON 数组,每个元素的内容和上面的 `/get_group_member_info` 接口相同,但对于同一个群组的同一个成员,获取列表时和获取单独的成员信息时,某些字段可能有所不同,例如 `area`、`title` 等字段在获取列表时无法获得,具体应以单独的成员信息为准。 + +### `/get_cookies` 获取 Cookies + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `domain` | string | 空 | 需要获取 cookies 的域名 | + +#### 响应数据 + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `cookies` | string | Cookies | + +### `/get_csrf_token` 获取 CSRF Token + +#### 参数 + +无 + +#### 响应数据 + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `token` | number (int32) | CSRF Token | + +### `/get_credentials` 获取 QQ 相关接口凭证 + +即上面两个接口的合并。 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `domain` | string | 空 | 需要获取 cookies 的域名 | + +#### 响应数据 + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `cookies` | string | Cookies | +| `csrf_token` | number (int32) | CSRF Token | + +### `/get_record` 获取语音 + +其实并不是真的获取语音,而是转换语音到指定的格式,然后返回语音文件名(`data\record` 目录下)。**注意,要使用此接口,需要安装 酷Q 的 [语音组件](https://cqp.cc/t/21132)。** + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `file` | string | - | 收到的语音文件名(CQ 码的 `file` 参数),如 `0B38145AA44505000B38145AA4450500.silk` | +| `out_format` | string | - | 要转换到的格式,目前支持 `mp3`、`amr`、`wma`、`m4a`、`spx`、`ogg`、`wav`、`flac` | +| `full_path` | boolean | `false` | 是否返回文件的绝对路径(Windows 环境下建议使用,Docker 中不建议) | + +#### 响应数据 + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `file` | string | 转换后的语音文件名或路径,如 `0B38145AA44505000B38145AA4450500.mp3`,如果开启了 `full_path`,则如 `C:\Apps\CoolQ\data\record\0B38145AA44505000B38145AA4450500.mp3` | + +### `/get_image` 获取图片 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `file` | string | - | 收到的图片文件名(CQ 码的 `file` 参数),如 `6B4DE3DFD1BD271E3297859D41C530F5.jpg` | + +#### 响应数据 + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `file` | string | 下载后的图片文件路径,如 `C:\Apps\CoolQ\data\image\6B4DE3DFD1BD271E3297859D41C530F5.jpg` | + +### `/can_send_image` 检查是否可以发送图片 + +#### 参数 + +无 + +#### 响应数据 + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `yes` | boolean | 是或否 | + +### `/can_send_record` 检查是否可以发送语音 + +#### 参数 + +无 + +#### 响应数据 + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `yes` | boolean | 是或否 | + +### `/get_status` 获取插件运行状态 + +#### 参数 + +无 + +#### 响应数据 + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `app_initialized` | boolean | HTTP API 插件已初始化 | +| `app_enabled` | boolean | HTTP API 插件已启用 | +| `plugins_good` | object | HTTP API 的各内部插件是否正常运行 | +| `app_good` | boolean | HTTP API 插件正常运行(已初始化、已启用、各内部插件正常运行) | +| `online` | boolean | 当前 QQ 在线,`null` 表示无法查询到在线状态 | +| `good` | boolean | HTTP API 插件状态符合预期,意味着插件已初始化,内部插件都在正常运行,且 QQ 在线 | + +通常情况下建议只使用 `online` 和 `good` 这两个字段来判断运行状态,因为随着插件的更新,其它字段有可能频繁变化。 + +其中,`online` 字段的在线状态检测有两种方式,可通过 `online_status_detection_method` 配置项切换,默认通过读取 酷Q 日志数据库实现,可切换为 `get_stranger_info` 以通过测试陌生人查询接口的可用性来检测。具体区别如下: + +| 在线检测方式 | 优点 | 缺点 | +| ---------- | --- | ---- | +| `get_stranger_info`(默认) | 正常情况下比 `log_db` 准确,但请求频率过高时可能变得不准确(在线被认为不在线);需要发送网络请求 | (几乎不可能)会因为 酷Q 更新而失效 | +| `log_db`| 查询速度较快;无需网络请求(不会触发腾讯风控);不会因为请求频率过高而不准确 | 可能因为 酷Q 修改数据库表名、文件名而失效;月尾掉线,月初无法检测到 | + +### `/get_version_info` 获取 酷Q 及 HTTP API 插件的版本信息 + +#### 参数 + +无 + +#### 响应数据 + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `coolq_directory` | string | 酷Q 根目录路径 | +| `coolq_edition` | string | 酷Q 版本,`air` 或 `pro` | +| `plugin_version` | string | HTTP API 插件版本,例如 `2.1.3` | +| `plugin_build_number` | number | HTTP API 插件 build 号 | +| `plugin_build_configuration` | string | HTTP API 插件编译配置,`debug` 或 `release` | + + +### `/set_restart_plugin` 重启 HTTP API 插件 + +由于重启插件同时需要重启 API 服务,这意味着当前的 API 请求会被中断,因此需在异步地重启插件,接口返回的 `status` 是 `async`。 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `delay` | number | `0` | 要延迟的毫秒数,如果默认情况下无法重启,可以尝试设置延迟为 2000 左右 | + +#### 响应数据 + +无 + +### `/clean_data_dir` 清理数据目录 + +用于清理积攒了太多旧文件的数据目录,如 `image`。 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `data_dir` | string | - | 收到清理的目录名,支持 `image`、`record`、`show`、`bface` | + +#### 响应数据 + +无 + +### `/clean_plugin_log` 清理插件日志 + +用于清空插件的日志文件。 + +#### 参数 + +无 + +#### 响应数据 + +无 + +## 试验性 API 列表 + +试验性 API 可以一定程度上增强实用性,但它们并非 酷Q 原生提供的接口,稳定性较差,不保证随时可用(如果不可用可以尝试重新登录 酷Q),且接口可能会在后面的版本中发生变动。除非必要,请尽量避免使用试验性接口。 + +所有试验性接口都以下划线(`_`)开头。 + +### `/_get_friend_list` 获取好友列表 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `flat` | boolean | `false` | 是否获取扁平化的好友数据,即所有好友放在一起、所有分组放在一起,而不是按分组层级 | + +#### 响应数据 + +当 `flat` 为 false 时,响应内容为 JSON 数组,每个元素为一个好友分组,格式如下: + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `friend_group_id` | number | 好友分组 ID | +| `friend_group_name` | string | 好友分组名称 | +| `friends` | array | 分组中的好友 | +| `friends[i].nickname` | string | 好友昵称 | +| `friends[i].remark` | string | 好友备注 | +| `friends[i].user_id` | number | 好友 QQ 号 | + +当 `flat` 为 true 时,响应内容为 JSON 对象,如下: + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `friend_groups` | array | 好友分组列表 | +| `friend_groups[i].friend_group_id` | number | 好友分组 ID | +| `friend_groups[i].friend_group_name` | string | 好友分组名称 | +| `friends` | array | 好友列表 | +| `friends[i].nickname` | string | 好友昵称 | +| `friends[i].remark` | string | 好友备注 | +| `friends[i].user_id` | number | 好友 QQ 号 | +| `friends[i].friend_group_id` | number | 好友所在分组 ID | + +### `/_get_group_info` 获取群信息 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `group_id` | number | - | 要查询的群号 | + +#### 响应数据 + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `group_id` | number | 群号 | +| `group_name` | string | 群名称 | +| `create_time` | number | 创建时间 | +| `category` | number | 群分类,具体这个 ID 对应的名称暂时没有 | +| `member_count` | number | 成员数 | +| `max_member_count` | number | 最大成员数(群容量) | +| `introduction` | string | 群介绍 | +| `admins` | array | 群主和管理员列表 | +| `admin_count` | number | 群主和管理员数 | +| `max_admin_count` | number | 最大群主和管理员数 | +| `owner_id` | number | 群主 QQ 号 | + +其中,`admins` 中每一项是一个 JSON 对象,如下: + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `user_id` | number | QQ 号 | +| `nickname` | string | 昵称 | +| `role` | string | 角色,`owner` 表示群主、`admin` 表示管理员 | + +注意,和其它接口有所不同,这里的所有字段都有可能在返回数据中不存在,例如可能缺少 `max_member_count` 等,在使用时请注意异常处理。 + +### `/_get_vip_info` 获取会员信息 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `user_id` | number | - | 要查询的 QQ 号 | + +#### 响应数据 + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `user_id` | number | QQ 号 | +| `nickname` | string | 昵称 | +| `level` | number | QQ 等级 | +| `level_speed` | number | 等级加速度 | +| `vip_level` | number | 会员等级 | +| `vip_growth_speed` | number | 会员成长速度 | +| `vip_growth_total` | string | 会员成长总值 | + +### `/_get_group_notice` 获取群公告 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `group_id` | number | - | 群号 | + +#### 响应数据 + +包含历史公告的数组,示例如下: + +```json +[ + { + "cn": 0, + "fid": "3b130f28000000006ef0a95cef090f00", + "fn": 0, + "msg": { + "text": "喵~ 喵~", + "text_face": "喵~  喵~", + "title": "喵喵喵" + }, + "pubt": 1554641006, + "read_num": 1, + "settings": { + "is_show_edit_card": 0, + "remind_ts": 0 + }, + "u": 3281334718, + "vn": 0 + } +] +``` + +这里的数据是 QQ 接口返回的原始数据,其中,`text` 和 `title` 等字段的内容被进行了 HTML 转义(如 ` `);除此之外,还可能会存在一些特殊二进制值,用于表示特殊内容,具体含义可能需要自行理解。 + +### `/_send_group_notice` 发布群公告 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `group_id` | number | - | 群号 | +| `title` | string | - | 标题 | +| `content` | string | - | 内容 | + +#### 响应数据 + +无 + +### `/_set_restart` 重启 酷Q,并以当前登录号自动登录(需勾选快速登录) + +**由于强行退出可能导致 酷Q 数据库损坏而影响功能,此接口除非必要请尽量避免使用。** + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `clean_log` | boolean | `false` | 是否在重启时清空 酷Q 的日志数据库(`log*.db`) | +| `clean_cache` | boolean | `false` | 是否在重启时清空 酷Q 的缓存数据库(`cache.db`) | +| `clean_event` | boolean | `false` | 是否在重启时清空 酷Q 的事件数据库(`eventv2.db`) | + +#### 响应数据 + +无 + +## 隐藏 API 列表 + +隐藏 API 是完全不建议正常用户使用的,它们只应该在插件内部或由 SDK 使用,因为不正确的使用可能造成插件运行不正常。 + +所有隐藏 API 都以点号(`.`)开头。 + +### `/.check_update` 检查更新 + +此接口 `status` 会返回 `async`,检查更新操作将会在线程池执行。 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `automatic` | boolean | `false` | 是否自动进行,如果为 true,将不会弹窗提示,而仅仅输出日志,同时如果 `auto_perform_update` 为 true,则会自动更新(需要手动重启 酷Q) | + +#### 响应数据 + +无 + +### `/.handle_quick_operation` 对事件执行快速操作 + +#### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `context` | object | - | 事件上报的数据对象 | +| `operation` | object | - | 快速操作对象,例如 `{"ban": true, "reply": "请不要说脏话"}` | + +#### 响应数据 + +无 + +## 获取 `data` 目录中的文件的接口 + +除了上面的 API,插件还提供一个简单的静态文件获取服务,请求方式只支持 HTTP 的 GET,URL 路径为 `/data/` 加上要请求的文件相对于 酷Q `data` 目录的路径。例如,假设 酷Q 主目录在 `C:\Apps\CQA`,则要获取 `C:\Apps\CQA\data\image\ABCD.jpg.cqimg` 的话,只需请求 `/data/image/ABCD.jpg.cqimg`,响应内容即为要请求的文件。 + +和上面的其它请求一样,如果配置文件中指定了 access token,则每次请求需要在请求头中加入验证头 `Authorization: Bearer your-token`。 + +另外,请求的路径中不允许出现 `..`,即上级目录的标记,以防止恶意或错误的请求到系统中的其它文件。 + +本功能默认情况下不开启,在配置文件中将 `serve_data_files` 设置为 `yes` 或 `true` 即可开启,见 [配置文件说明](/Configuration)。 diff --git a/docs/4.13/CQCode.md b/docs/4.13/CQCode.md new file mode 100644 index 0000000..312e85e --- /dev/null +++ b/docs/4.13/CQCode.md @@ -0,0 +1,77 @@ +# CQ 码 + +CQ 码的使用方式和 酷Q 原生的 CQ 码兼容(关于原生 CQ 码的使用,请看 酷Q 文档的 [CQ码](https://docs.cqp.im/manual/cqcode/)),在要发送的消息中插入相应的代码即可,例如: + +``` +[CQ:face,id=14] [CQ:image,file=1.jpg] +``` + +对于字符串格式表示的消息,使用方式和原生 CQ 码完全兼容**意味着需要对特殊字符字符进行转义**,由于很多时候我们不需要使用 CQ 码,只需要发送文字消息就行了,这种情况下可以在请求 API 时加入 `auto_escape` 参数,这将会自动对整个消息的特殊字符进行转义,具体请看 [API 描述](/API)。 + +而使用数组格式的消息段来表示 CQ 码,则无需进行转义。 + +除了原生的 CQ 码,CoolQ HTTP API 还提供了一些实用的增强功能(对字符串和数组格式的消息均有效,下面将以字符串为例),称之为「增强 CQ 码」。 + +## 增强功能列表 + +### 发送 + +#### 发送网络图片或语音 + +酷Q 原生的 CQ 码只能发送 `data\image` 文件夹里的图片、`data\record` 里的语音,增强 CQ 码支持设置 `file` 为网络链接,内部会首先把图片或语音下载到 `data` 中相应的文件夹,然后把 `file` 替换成下载好的本地文件名。例如: + +``` +[CQ:image,file=http://i1.piimg.com/567571/fdd6e7b6d93f1ef0.jpg] +[CQ:record,file=http://doora.qiniudn.com/35aIm.silk] +``` + +由于从网络下载可能比较耗时,插件默认情况下会在第二次发送同一链接时,直接采用本地缓存,如果要发送的图片或语音的链接内容有变,不宜使用缓存,则可以在 CQ 码中加入参数 `cache=0` 来禁用缓存(仅本次有效),例如: + +``` +[CQ:image,cache=0,file=http://i1.piimg.com/567571/fdd6e7b6d93f1ef0.jpg] +``` + +另外,插一个题外话,如果要发送非 SILK 格式的音频文件,需要安装 酷Q 的 [语音组件](https://cqp.cc/t/21132),否则会出现错误码 -11。 + +#### 发送文件系统中另一个地方的图片或语音 + +除了发送网络上的图片、语音,还可以发送本地文件系统中其它地方的图片、语音,使用 [`file` URI](https://tools.ietf.org/html/rfc8089) 格式,例如: + +``` +[CQ:image,file=file:///C:\Users\richard\Pictures\1.png] +[CQ:record,file=file:///C:\Users\richard\Music\1.mp3] +``` + +#### 发送 base64 编码的图片或语音 + +除了指定实体文件,也可以直接将文件用 base64 编码后放在 CQ 码参数中传递,使用 `base64://` 加 base64 编码,例如: + +``` +[CQ:image,file=base64://iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAIAAADJt1n/AAAAKElEQVQ4EWPk5+RmIBcwkasRpG9UM4mhNxpgowFGMARGEwnBIEJVAAAdBgBNAZf+QAAAAABJRU5ErkJggg==] +``` + +### 接收 + +#### 提取 cqimg 文件中的实际图片 URL + +酷Q 收到的图片会放在 `data\image` 中,并且以文件名加 `.cqimg` 扩展名的形式存储为纯文本文件,实际的图片 URL 就在里面的 `url` 字段,增强 CQ 码会自动提取这个 URL,并添加到 CQ 码的 `url` 参数中。 + +例如,假设原 CQ 码如下: + +``` +[CQ:image,file=AE3062186A2073B33AB1F2BB2F58F3A4.jpg] +``` + +提取 URL 后,会更改为: + +``` +[CQ:image,file=AE3062186A2073B33AB1F2BB2F58F3A4.jpg,url=http://183.232.95.26/offpic_new/1002647525//8102132e-4ab0-46cf-a8e1-2f62185232cb/0] +``` + +如果提取不成功(读取文件失败),则不变。 + +**另外请注意,这个 URL 会在一定时间后过期(不确定多久),但 酷Q 在收到以前收过的图之后,仍然会返回同样的文件名,因此建议定期清理 `data\image` 目录以防止 URL 失效。** + +## 原生 CQ 码的非官方补充 + +CQ 码虽然在一定程度上具有较强的消息表达能力,但由于 QQ 的经常更新以及 酷Q 协议的更新不及时,导致 CQ 码的使用中会遇到很多坑。要重新整理一份完整的 CQ 码列表比较麻烦,因此这里只给出一条一条的坑的记录,见 [CQ 码的坑](https://github.com/richardchien/coolq-http-api/wiki/CQ-%E7%A0%81%E7%9A%84%E5%9D%91)。 diff --git a/docs/4.13/CommunicationMethods.md b/docs/4.13/CommunicationMethods.md new file mode 100644 index 0000000..2d7b6b6 --- /dev/null +++ b/docs/4.13/CommunicationMethods.md @@ -0,0 +1,121 @@ +# 通信方式 + +目前支持三种通信方式: + +- 插件作为 HTTP 服务端,提供 API 和数据文件获取服务 +- 插件作为 WebSocket 服务端,通过 `/api/` 和 `/event/` 两个接口分别提供 API 调用和事件推送服务 +- 插件作为 WebSocket 客户端(称为「反向 WebSocket」),主动连接给定的 API 和事件上报地址,分别提供 API 调用服务和事件上报服务 + +上面三种通信方式分别使用 `use_http`、`use_ws`、`use_ws_reverse` 三个配置项来开关。 + +除了上述通信方式,还有通过 HTTP 上报事件,这是永远可用的,**不受上面三个 `use_*` 配置控制**,只要配置了 `post_url`,就会上报,并且处理响应数据。 + +下面详细介绍上面的三种通信方式的适用场景和使用方法,你可以根据需要选择其一或者适当组合使用。 + +## 插件作为 HTTP 服务端 + +### 适用场景 + +这是本插件最初支持的通信方式,也是使用起来最方便快捷的方式,适用于以下情况: + +- 在本地初步测试使用 酷Q 和本插件,需要快速测试接口、查看接口返回的数据 +- 运行 酷Q 的机器有公网 IP,或 酷Q 和业务代码运行在同一机器上 +- 对于数据文件访问有需求 +- ... + +### 使用方法 + +将 `use_http` 配置为 `true`(默认即 `true`),然后通过 `host`、`port` 来配置要监听的 IP 和端口(默认为 `0.0.0.0:5700`),启用插件后即可通过形如 `http://host:port/send_private_msg?user_id=1234567&message=hello` 的 URL 来调用 API。 + +具体的 API 调用方法和 API 列表见 [API 描述](/API)。 + +## 插件作为 WebSocket 服务端 + +### 适用场景 + +- 运行 酷Q 的机器有公网 IP,或 酷Q 和业务代码运行在同一机器上 +- 业务代码运行环境无法通过 HTTP 上报获得事件(例如浏览器中) +- ... + +### 使用方法 + +将 `use_ws` 配置为 `true`(默认 `false`),然后通过 `ws_host`、`ws_port` 来配置要监听的 IP 和端口(默认为 `0.0.0.0:6700`),启用插件后即可通过 `ws://ws_host:ws_port/api/` 接口来调用 API,通过 `ws://ws_host:ws_port/event/` 来接收事件推送,通过 `ws://ws_host:ws_port/` 接口来在同一条连接上调用 API 和接收事件推送(相当于 `/api/` 和 `/event/` 接口的合并,对接收到的数据可通过 `post_type` 字段来判断是 API 响应还是事件)。 + +这两个接口的具体用法见 [WebSocket API 描述](/WebSocketAPI)。 + +## 插件作为 WebSocket 客户端(反向 WebSocket) + +### 适用场景 + +- 运行 酷Q 的机器没有公网 IP,且业务代码有公网 IP,或两者运行在同一机器上 +- ... + +### 使用方法 + +在业务代码中启动 WebSocket 服务端,开启两个接口,分别用于 API 调用和事件上报(如果只需要一个功能,也可以只开一个),然后分别配置 `ws_reverse_api_url`、`ws_reverse_event_url` 为上述两个接口的完整地址,例如 `ws://127.0.0.1:8765/api/`。再将 `use_ws_reverse` 配置为 `true`(默认为 `false`),重启插件即可开启反向 WebSocket 服务。 + +插件会在特定的时候向指定的 URL 建立连接,并且在请求头中通过 `X-Self-ID` 来表示当前正在建立连接的机器人 QQ 号,以及通过 `X-Client-Role` 来表示当前正在建立连接的客户端类型,如: + +```http +X-Self-ID: 123456 +X-Client-Role: Event +``` + +其中,`X-Client-Role` 可能为 `Event` 和 `API`,分别对应事件上报和 API 的两个连接。`X-Client-Role` 头的存在意味着你可以将 `ws_reverse_api_url` 和 `ws_reverse_event_url` 设置为相同的地址,或简单地使用 `ws_reverse_url` 来配置共用地址即可,然后只需要在 WebSocket 后端对请求头进行判断即可知道是哪个账号的哪个客户端在连接。 + +除了使用 API 和 Event 双连接的方式,还可以通过将配置项 `ws_reverse_use_universal_client` 设为 `true`(默认 `false`)来让插件**只向 `ws_reverse_url` 建立一条连接**,`X-Client-Role` 为 `Universal`,API 和 Event 的数据均从这条连接上传输(相当于 API 和 Event 客户端的合并,对接收到的数据可通过 `post_type` 字段来判断是 API 响应还是事件)。Universal 客户端单连接的使用方式和分开的 API 和 Event 完全一致,下面不在单独说明。 + +如果配置了 `access_token`,则在建立连接时,还会加入 `Authorization` 请求头,例如: + +```http +Authorization: Token kSLuTF2GC2Q4q4ugm3 +X-Self-ID: 123456 +``` + +> 注意:这里本应该是 `Authorization: Bearer kSLuTF2GC2Q4q4ugm3`(和插件作为服务端的校验保持一致),但由于历史上的某次升级时忘记把这里的 `Token` 改为 `Bearer`,并且如果现在修改可能会对已有代码造成破坏,因此决定保持为 `Token` 不变。 + +#### API 调用 + +首先插件启用时会启动一个**保持连接**的客户端用于连接 API 调用接口,即 `ws_reverse_api_url` 指定的接口,一旦收到服务端发来的消息就会调用相应的 API 并返回调用结果。 + +API 的调用方式和插件作为 WebSocket 服务端的 `/api/` 接口使用方式相同,见 [WebSocket API 描述的 `/api/`](/WebSocketAPI#api),不同在于你的服务端必须在调用 API 后保持连接,以便下次调用。 + +#### 事件上报 + +插件启动时会启动一个**保持连接**的客户端用于连接事件上报接口,即 `ws_reverse_event_url` 指定的接口,在后续接收到 酷Q 的事件时,会通过这个连接发送事件数据。发送事件数据格式和 HTTP POST 方式上报的完全一致,见 [上报数据格式](/Post#上报数据格式),事件列表见 [事件列表](/Post#事件列表)。 + +与 HTTP 上报不同的是,这里上报不会对数据进行签名(即 HTTP 上报中的 `X-Signature` 请求头在这里没有等价的东西),并且也不会处理响应数据。 + +### 断线重连 + +可通过配置项 `ws_reverse_reconnect_interval` 和 `ws_reverse_reconnect_on_code_1000` 来配置反向 WebSocket 的断线重连机制,分别设置尝试重连的时间间隔,和是否在关闭码 1000 的情况下进行重连。 + +如果你的服务器重启时插件没有自动重连,建议尝试设置 `ws_reverse_reconnect_on_code_1000 = yes`。 + +## WebSocket 的 API 调用响应顺序问题 + +由于 WebSocket 的通信不像 HTTP 那样是固定的一来一回,而是一直保持连接,大多 WebSocket 框架都采用事件驱动的方式来提供接口。这就导致,在通过 WebSocket 进行**连续** API 调用时,很多情况下无法确切地知道插件返回的响应是对应哪次调用。因此插件现加入了 echo 机制,允许用户在调用 API 时在调用数据(JSON 对象)中加入一个 `echo` 字段(数据类型任意),以标记此次调用,插件会在该调用的响应数据中将其原样返回。 + +### 调用示例 + +```json +{ + "action": "send_private_msg", + "params": { + "user_id": 123456, + "message": "你好" + }, + "echo": 1648451782 +} +``` + +### 响应示例 + +```json +{ + "status": "ok", + "retcode": 0, + "data": null, + "echo": 1648451782 +} +``` diff --git a/docs/4.13/Configuration.md b/docs/4.13/Configuration.md new file mode 100644 index 0000000..c9e4f0d --- /dev/null +++ b/docs/4.13/Configuration.md @@ -0,0 +1,193 @@ +# 配置 + +配置文件支持 INI 和 JSON 两种格式,并支持单个文件配置多个账号,或每个账号对应一个配置文件。 + +插件启动时(或重启时)按如下顺序依次尝试加载配置文件,一旦有一条加载成功,就停止加载(所有路径均为相对于 `data\app\io.github.richardchien.coolqhttpapi` 的相对路径): + +- `config.(cfg|ini)`(扩展名的括号和竖线表示优先加载 `.cfg`,若没有,则加载 `.ini`,下同),文件中通用配置需要放在 `[general]` 下,QQ 号特定配置放在 `[]` 下 +- `config\general.(cfg|ini)` + `config\.(cfg|ini)`,前者是通用配置,全部放在 `[general]` 下,后者是 QQ 号特定配置,全部放在 `[]` 下,后者覆盖前者中已存在的内容 +- `config.json`,通用配置需放在根对象的 `general` 字段,QQ 号特定配置放在 QQ 号对应字段,例如 `{"general": {"host": "0.0.0.0"}, "123456": {"port": 6666}}` +- `config\general.json` + `config\.json`,配置项均直接放在根对象,后者覆盖前者中已存在的内容 + +**重要:如果配置文件中需要使用中文或其它非 ASCII 字符,则必须使用 UTF-8 without BOM 编码保存文件!** + +## 几种典型的配置文件安排方式 + +### 使用 INI 格式,在单个文件中存放多个账号的配置 + +- `data\app\io.github.richardchien.coolqhttpapi\config.ini` + +```ini +[general] +host = 0.0.0.0 +post_url = http://192.168.0.11:8888 + +[12345678] +access_token = Mgep4rV49rM8Jf +port = 5700 + +[87654321] +port = 5701 +``` + +### 使用 JSON 格式,在单个文件中存放多个账号的配置 + +- `data\app\io.github.richardchien.coolqhttpapi\config.json` + +```json +{ + "general": { + "host": "0.0.0.0", + "post_url": "http://127.0.0.1:8080" + }, + "12345678": { + "access_token": "Mgep4rV49rM8Jf", + "port": 5700 + }, + "87654321": { + "port": 5701 + } +} +``` + +### 使用 JSON 格式,每个账号对应一个配置文件 + +- `data\app\io.github.richardchien.coolqhttpapi\config\general.json` + +```json +{ + "host": "0.0.0.0", + "post_url": "http://127.0.0.1:8080" +} +``` + +- `data\app\io.github.richardchien.coolqhttpapi\config\12345678.json` + +```json +{ + "access_token": "Mgep4rV49rM8Jf", + "port": 5700 +} +``` + +- `data\app\io.github.richardchien.coolqhttpapi\config\87654321.json` + +```json +{ + "port": 5701 +} +``` + +## 配置项 + +| 配置项名称 | 默认值 | 说明 | +| -------- | ------ | --- | +| `host` | `[::]` | HTTP 服务器监听的 IP | +| `port` | `5700` | HTTP 服务器监听的端口 | +| `use_http` | `true` | 是否开启 HTTP 接口,即通过 HTTP 调用 API,见 [通信方式的第一种](/CommunicationMethods#插件作为-http-服务端) | +| `ws_host` | `[::]` | WebSocket 服务器监听的 IP | +| `ws_port` | `6700` | WebSocket 服务器监听的端口 | +| `use_ws` | `false` | 是否开启 WebSocket 服务器,可用于调用 API 和推送事件,见 [通信方式的第二种](/CommunicationMethods#插件作为-websocket-服务端) | +| `ws_reverse_url` | 空 | 反向 WebSocket Event 和事件上报的共用地址 | +| `ws_reverse_api_url` | 空 | 反向 WebSocket API 地址,如果为空,则使用 `ws_reverse_url` 指定的值 | +| `ws_reverse_event_url` | 空 | 反向 WebSocket 事件上报地址,如果为空,则使用 `ws_reverse_url` 指定的值 | +| `ws_reverse_reconnect_interval` | `3000` | 反向 WebSocket 客户端断线重连间隔,单位毫秒 | +| `ws_reverse_reconnect_on_code_1000` | `true` | 是否在关闭状态码为 1000 的时候重连 | +| `ws_reverse_use_universal_client` | `false` | 是否使用 Universal 客户端 | +| `use_ws_reverse` | `false` | 是否使用反向 WebSocket 服务,即插件作为 WebSocket 客户端主动连接指定的 API 和事件上报地址,见 [通信方式的第三种](/CommunicationMethods#插件作为-websocket-客户端(反向-websocket)) | +| `post_url` | 空 | 消息和事件的上报地址,通过 POST 方式请求,数据以 JSON 格式发送 | +| `post_timeout` | `0` | HTTP 上报(即访问 `post_url`)的超时时间,单位秒,0 表示不设置超时 | +| `access_token` | 空 | API 访问 token,如果不为空,则会在接收到请求时验证 `Authorization` 请求头是否为 `Bearer xxxxxxxx`,`xxxxxxxx` 为 access token | +| `secret` | 空 | 上报数据签名密钥,如果不为空,则会在 HTTP 上报时对 HTTP 正文进行 HMAC SHA1 哈希,使用 `secret` 的值作为密钥,计算出的哈希值放在上报的 `X-Signature` 请求头,例如 `X-Signature: sha1=f9ddd4863ace61e64f462d41ca311e3d2c1176e2` | +| `post_message_format` | `string` | 上报消息格式,`string` 为字符串格式,`array` 为数组格式,具体见 [消息格式](/Message) | +| `serve_data_files` | `false` | 是否提供请求 `data` 目录的文件的功能 | +| `update_source` | v4.12.3 之前 `github`
v4.12.3 及之后 `china` | 更新源,可选 `global`/`github` 和 `china`/`coding` | +| `update_channel` | `stable` | 更新通道,目前有 `stable`、`beta`、`alpha` 三个 | +| `auto_check_update` | `false` | 是否自动检查更新(每次启用插件时检查),不启用的情况下,仍然可以在 酷Q 应用菜单中手动检查更新 | +| `auto_perform_update` | `false` | 是否自动执行更新,仅在 `auto_check_update` 启用时有效,若启用,则插件将在自动检查到更新后,自动下载新版本(需要手动重启 酷Q 以生效) | +| `thread_pool_size` | `4` | 工作线程池大小,用于异步发送消息和一些其它小的异步任务,应根据计算机性能和实际需求适当调节,若设为 0,则使用 `CPU 核心数 * 2 + 1` | +| `server_thread_pool_size` | `4` | API 服务器线程池大小,用于异步处理请求,应根据计算机性能和实际需求适当调节,若设为 0,则使用 `CPU 核心数 * 2 + 1` | +| `convert_unicode_emoji` | `true` | 是否在 CQ:emoji 和实际的 Unicode 之间进行转换,转换可能耗更多时间,但日常情况下影响不大,如果你的机器人需要处理非常大段的消息(上千字),且对性能有要求,可以考虑关闭转换 | +| `event_filter` | 空 | 指定事件过滤规则文件,见 [事件过滤器](/EventFilter),留空将不开启事件过滤器 | +| `enable_backward_compatibility` | `false` | 是否启用旧版兼容性,启用时**事件上报**的数据将和 3.x 版本保持兼容 | +| `show_log_console` | `true` | 是否显示日志输出控制台 | +| `max_log_file_size` | `6291456` | 最大单日志文件大小,单位字节,默认 6 MB | +| `max_log_files` | `1` | 最大日志文件备份数量(采用日志轮替机制) | +| `log_level` | `info` | 日志文件和日志控制台的日志等级,可选 `debug`、`info`、`warning`、`error`、`fatal` | +| `use_extension` | `false` | 是否启用扩展机制,见 [扩展](/Extension) | +| `disable_coolq_log` | `true` | 是否禁用 酷Q 原生日志,由于使用 酷Q 原生日志可能会导致快速重启时插件卡死,所以默认禁用,如果你不在乎重启时卡死,并且需要在 酷Q 原生日志窗口查看插件的日志,可以将此项设为 `false` | +| `online_status_detection_method` | `get_stranger_info` | QQ 在线状态检测方式,默认(`get_stranger_info`)通过陌生人查询接口判断,设为 `log_db` 可切换成从 酷Q 的日志数据库判断,具体区别见 [其 API 说明](/API#get_status-获取插件运行状态) | +| `enable_heartbeat` | `false` | 是否启用心跳机制,启用时会产生类型为 `heartbeat` 的元事件,见 [元事件](/Post#元事件) | +| `heartbeat_interval` | `15000` | 产生心跳元事件的时间间隔,单位毫秒 | +| `enable_rate_limited_actions` | `false` | 是否启用限速 API 调用的支持 | +| `rate_limit_interval` | `500` | 限速 API 调用的排队间隔时间,单位毫秒 | + +## 几种常用的配置项组合 + +注意,将下面的 JSON 复制到插件配置文件时,请确保逗号正确,并且删掉注释。 + +### 本地开发环境 + +```json +{ + "log_level": "debug", // 输出调试级别日志 + "show_log_console": true, // 显示日志控制台 + + // 如果想要在酷Q的运行日志中查看插件日志,也可以加上下面这项 + "disable_coolq_log": false +} +``` + +### 自动更新插件 + +```json +{ + "update_source": "china", + "update_channel": "stable", + "auto_check_update": true, + "auto_perform_update": true +} +``` + +现不再支持自动更新后自动重启 酷Q,需手动重载应用以生效。 + +### 生产环境 + +```json +{ + // 关闭不用的功能,例如使用正向 WebSocket 时: + "use_http": false, + "use_ws": true, + "use_ws_reverse": false, + "post_url": "", + + // 安全相关 + "access_token": "some-token", + "secret": "some-secret", + + // 关闭自动更新(默认就是关闭的) + "auto_check_update": false, + "auto_perform_update": false, + + // 根据 CPU 核心数适当选择线程池大小 + "thread_pool_size": 6, + "server_thread_pool_size": 8, + + // 如有需要,使用过滤器避免不必要的上报 + "event_filter": "filter.json", + + // 日志相关 + "show_log_console": true, // 看需求,如果不需要通过 GUI 查看日志,这里推荐关闭 + "max_log_file_size": 6291456, // 单日志文件最大字节数,6 MB + "max_log_files": 3, + "log_level": "info", // 消息量特别大的情况下,可以酌情设置为 warning + + // 心跳 + "enable_heartbeat": true, + "heartbeat_interval": 15000, // 15 秒一个心跳包 + + // 请求频率限制 + "enable_rate_limited_actions": true, + "rate_limit_interval": 300 // 300 毫秒一条消息 +} +``` diff --git a/docs/4.13/Docker.md b/docs/4.13/Docker.md new file mode 100644 index 0000000..9ad6506 --- /dev/null +++ b/docs/4.13/Docker.md @@ -0,0 +1,44 @@ +# Docker + +酷Q 目前可以在 Wine 中运行,见 [酷Q Air / Pro on Wine](https://cqp.cc/t/30966),因此也就自然而然有了相应的 Docker 镜像 [coolq/wine-coolq](https://hub.docker.com/r/coolq/wine-coolq/)。 + +要在 Docker 中使用本插件,你可以使用 酷Q 官方的 Docker 镜像,然后在其中安装本插件(下载 cpk、编辑配置文件、启用插件),也可以使用我维护的已安装并启用了插件的镜像 [richardchien/cqhttp](https://hub.docker.com/r/richardchien/cqhttp/)(基于 酷Q 官方的镜像修改)。下面介绍这个镜像的用法。 + +## 基本用法 + +```bash +$ docker pull richardchien/cqhttp:latest +$ mkdir coolq # 用于存储 酷Q 的程序文件 +$ docker run -ti --rm --name cqhttp-test \ + -v $(pwd)/coolq:/home/user/coolq \ # 将宿主目录挂载到容器内用于持久化 酷Q 的程序文件 + -p 9000:9000 \ # noVNC 端口,用于从浏览器控制 酷Q + -p 5700:5700 \ # HTTP API 插件开放的端口 + -e COOLQ_ACCOUNT=123456 \ # 要登录的 QQ 账号,可选但建议填 + -e CQHTTP_POST_URL=http://example.com:8080 \ # 事件上报地址 + -e CQHTTP_SERVE_DATA_FILES=yes \ # 允许通过 HTTP 接口访问 酷Q 数据文件 + richardchien/cqhttp:latest +``` + +其中,`CQHTTP_POST_URL`、`CQHTTP_SERVE_DATA_FILES` 是用于配置插件运行的,格式为「`CQHTTP_` + 插件配置项的大写」,具体的配置项,见 [配置](/Configuration)。 + +然后访问 `http://<你的IP>:9000/` 进入 noVNC(默认密码 `MAX8char`),登录 酷Q,即可开始使用(插件已自动启用,配置文件也根据启动命令的环境变量自动生成了)。一般情况下,你不太需要关注插件是如何存在于容器中的。 + +注意,默认情况下,容器启动时会检查是否已经存在 `config` 目录,如果不存在,则会将 `CQHTTP_` 开头的环境变量写入到配置文件中;如果 `config` 目录存在,即不是首次启动,则不会做任何修改。**因此,你可以在容器运行时手动修改配置文件,重启容器后仍然有效,这和旧版本的行为不一样!**如果你要让容器每次启动时都使用环境变量重新创建配置文件,以保持插件行为和容器启动命令的一致性,可以设置环境变量 `FORCE_ENV` 的值为 `true`。 + +## 通过环境变量配置容器的运行 + +| 环境变量名 | 说明 | +| -------- | ---- | +| `VNC_PASSWD` | 继承自官方镜像,noVNC 的密码(官方说不能超过 8 个字符,实测可以超过,但只会验证前 8 位) | +| `COOLQ_ACCOUNT` | 继承自官方镜像,设置要登录 酷Q 的 QQ 号。在第一次手动登录后,你可以勾选「快速登录」功能以启用自动登录,此后,容器启动或 酷Q 异常退出时,会自动登录该帐号。 | +| `COOLQ_URL` | 继承自官方镜像,设置 酷Q 的下载链接,默认为 `http://dlsec.cqp.me/cqa-tuling`,即 酷Q Air 图灵版。如需使用 酷Q Pro,可改为 `https://dlsec.cqp.me/cqp-tuling`。也可使用任何其它可下载的 URL,只要确保下载后的 zip 文件能解压出 `酷Q Air/CQA.exe` 或 `酷Q Pro/CQP.exe` | +| `FORCE_ENV` | 是否强制把 `CQHTTP_` 开头的环境变量写入配置文件,**这会删除现有的配置文件** | +| `CQHTTP_POST_URL`
`CQHTTP_SERVE_DATA_FILES`
`CQHTTP_USE_WS`
等形如 `CQHTTP_*` 的 | 当容器首次启动或 `FORCE_ENV` 为 `true` 的情况下,容器会将这些项的值自动写入配置文件 | + +## 更换/升级插件版本 + +Docker 镜像使用 tag 来标记版本,插件版本 3.0.0 之后的 richardchien/cqhttp 镜像遵循了这一点(旧版本没有,已移至镜像的 `legacy` 标签)。 + +上一节的示例给出的命令拉取了 `richardchien/cqhttp:latest`,即当前最新版本(稳定版),如果你需要更新插件到最新版本,重新拉取一次 `latest` 标签即可,如果你需要使用指定版本的插件,如 `3.0.0` 版本,则使用镜像 `richardchien/cqhttp:3.0.0`。插件的 GitHub 仓库中的每个 release 对应 docker 镜像的一个 tag,**注意,release 的标题中的版本号有 `v` 开头,docker 镜像的 tag 没有**。 + +此外,Docker 容器在每次运行时,会将相应版本的 cpk 文件复制到 酷Q 的 app 目录,并覆盖已有的文件(假设有的话)。这意味着,**当使用某个版本的 docker 镜像时,如果你自行更换了 cpk 文件,那么下次容器重启时将会重新覆盖它**。并且,无法使用插件的检查更新功能来更新。如果你不要这个行为,可以删除 `app\io.github.richardchien.coolqhttpapi\version.lock` 文件以解除版本锁;如果要恢复默认行为,重新创建这个文件即可。 diff --git a/docs/4.13/EventFilter.md b/docs/4.13/EventFilter.md new file mode 100644 index 0000000..fc867e4 --- /dev/null +++ b/docs/4.13/EventFilter.md @@ -0,0 +1,133 @@ +# 事件过滤器 + +将配置项 `event_filter` 设置为过滤规则文件名即可开启事件过滤器,例如 `event_filter = filter.json` 将会指定 酷Q 主目录中的 `data\app\io.github.richardchien.coolqhttpapi\filter.json` 作为过滤规则文件,插件启动时会读取该文件中定义的过滤规则(使用 JSON 编写),若文件不存在,或过滤规则语法错误,则会暂停所有上报。 + +## 示例 + +这节首先给出一些示例,演示过滤器的基本用法,下一节将给出具体语法说明。 + +### 只上报以「!!」开头的消息 + +```json +{ + "raw_message": { + ".regex": "^!!" + } +} +``` + +### 只上报群组的非匿名消息 + +```json +{ + "message_type": "group", + "anonymous": { + ".eq": null + } +} +``` + +### 只上报私聊或特定群组的非匿名消息 + +```json +{ + ".or": [ + { + "message_type": "private" + }, + { + "message_type": "group", + "group_id": { + ".in": [ + 123456 + ] + }, + "anonymous": { + ".eq": null + } + } + ] +} +``` + +### 只上报群组 11111、22222、33333 中不是用户 12345 发送的消息,以及用户 66666 发送的所有消息 + +```json +{ + ".or": [ + { + "group_id": { + ".in": [11111, 22222, 33333] + }, + "user_id": { + ".neq": 12345 + } + }, + { + "user_id": 66666 + } + ] +} +``` + +### 一个更复杂的例子 + +```json +{ + ".or": [ + { + "message_type": "private", + "user_id": { + ".not": { + ".in": [11111, 22222, 33333] + }, + ".neq": 44444 + } + }, + { + "message_type": { + ".regex": "group|discuss" + }, + ".or": [ + { + "group_id": 12345 + }, + { + "raw_message": { + ".contains": "通知" + } + } + ] + } + ] +} +``` + +## 语法说明 + +过滤规则最外层是一个 JSON 对象,其中的键,如果以 `.`(点号)开头,则表示运算符,其值为运算符的参数,如果不以 `.` 开头,则表示对事件数据对象中相应键的过滤。过滤规则中任何一个对象,只有在它的所有项都匹配的情况下,才会让事件通过(等价于一个 `and` 运算);其中,不以 `.` 开头的键,若其值不是对象,则只有在这个值和事件数据相应值相等的情况下,才会通过(等价于一个 `eq` 运算符)。 + +下面列出所有运算符(「要求的参数类型」是指运算符的键所对应的值的类型,「可作用于的类型」是指在过滤时事件对象相应值的类型): + +| 运算符 | 要求的参数类型 | 可作用于的类型 | +| ----- | ------------ | ----------- | +| `.not` | object | 任何 | +| `.and` | object | 若参数中全为运算符,则任何;若不全为运算符,则 object | +| `.or` | array(数组元素为 object) | 任何 | +| `.eq` | 任何 | 任何 | +| `.neq` | 任何 | 任何 | +| `.in` | string/array | 若参数为 string,则 string;若参数为 array,则任何 | +| `.contains` | string | string | +| `.regex` | string | string | + +插件在启动时读取过滤规则,如果读到无法识别的运算符,或「要求的参数类型」不符,则认为语法错误,将停止所有上报;在实际运行中执行过滤时,如果事件数据的类型和「可作用于的类型」不符,则认为过滤不通过。 + +## 过滤时的事件数据对象 + +过滤器在插件构建好事件数据后运行,各事件的数据字段见 [事件上报](/Post) 及其中的 [事件列表](/Post#事件列表)。 + +这里有几点需要注意: + +- `enable_backward_compatibility` 配置项**不会**影响这里的事件数据对象,也就是说,即使 `enable_backward_compatibility` 设置为 `yes`,过滤器所看到的事件数据的字段和值也不会改变 +- `message` 字段在运行过滤器时是消息段数组的形式(见 [消息格式](/Message)),无论配置文件中 `post_message_format` 是什么 +- `raw_message` 字段为未经 [增强 CQ 码](/CQCode) 处理的原始消息字符串,这意味着其中可能会出现形如 `[CQ:face,id=123]` 的 CQ 码 diff --git a/docs/4.13/Extension.md b/docs/4.13/Extension.md new file mode 100644 index 0000000..ad15665 --- /dev/null +++ b/docs/4.13/Extension.md @@ -0,0 +1,13 @@ +# 扩展 + +HTTP API 插件的扩展机制允许用户下载额外的 DLL 来扩展插件的功能,例如添加长轮询接口。扩展的目的不是取代 酷Q 原生的插件机制,而是为了方便向 HTTP API 插件添加新功能,同时不必将功能并入核心 CPK 文件。 + +## 扩展列表 + +目前可用的扩展列表,见 [扩展列表](https://github.com/richardchien/coolq-http-api/wiki/%E6%89%A9%E5%B1%95%E5%88%97%E8%A1%A8)。 + +## 使用方法 + +将 DLL 扩展文件(可在响应扩展的链接中找到下载地址)直接放入 酷Q 的 `data\app\io.github.richardchien.coolqhttpapi\extensions` 文件夹,然后将插件配置项 `use_extension` 设置为 `true` 再重启插件即可启用扩展。插件启动时会加载扩展文件夹中所有 `.dll` 结尾的、非 `_` 开头的动态库文件。 + +扩展通常还要求在配置文件中单独设置 `enable` 项才能实际启用,例如,长轮询扩展要求设置 `long_polling.enable` 配置项为 `true` 才会启用。具体请查看相应扩展提供的使用方法。 diff --git a/docs/4.13/Home.md b/docs/4.13/Home.md new file mode 100644 index 0000000..8754143 --- /dev/null +++ b/docs/4.13/Home.md @@ -0,0 +1,56 @@ +# CoolQ HTTP API 插件 + +## 简介 + +通过 HTTP 对 酷Q 的事件进行上报以及接收 HTTP 请求来调用 酷Q 的 DLL 接口,从而可以使用其它语言编写 酷Q 插件。现已支持 WebSocket。 + +## 使用方法 + +### 手动安装 + +直接到 [Releases](https://github.com/richardchien/coolq-http-api/releases) 下载最新的 cpk 文件放到 酷Q 的 app 文件夹,然后启用即可。由于要上报事件、接受调用请求,因此需要所有权限。如果 Releases 里面下载不了,也可以去 [百度网盘](https://pan.baidu.com/s/1qY55zp6) 下载。 + +注意如果 酷Q 启动时报错说插件加载失败,或者系统弹窗提示缺少 DLL 文件,则需要安装 [Visual C++ 可再发行软件包](https://aka.ms/vs/16/release/vc_redist.x86.exe)(**点击链接即可从官方下载,如果自行安装,一定要装 x86 也就是 32 位版本!**),如果你的系统是 Windows 7 或 Windows Server 2008、或者安装 Visual C++ 可再发行软件包之后仍然加载失败,则还需要安装 [通用 C 运行库更新](https://support.microsoft.com/zh-cn/help/3118401/update-for-universal-c-runtime-in-windows),在这个链接里选择你系统对应的版本下载安装即可。如果此时还加载失败,请尝试重启系统。 + +启用后插件将开启一个 HTTP 服务器来接收请求,默认监听 `0.0.0.0:5700`,首次启用会生成一个默认配置文件,在 酷Q 的 `data\app\io.github.richardchien.coolqhttpapi\config` 文件夹中,文件名为 `.json`(`` 为登录的 QQ 号),使用 JSON 格式填写。关于配置项的说明,见 [配置](/Configuration)。 + +此时通过 `http://192.168.1.123:5700/` 即可调用 酷Q 的函数,例如 `http://192.168.1.123:5700/send_private_msg?user_id=123456&message=你好`,注意这里的 `192.168.1.123` 要换成你自己电脑的 IP,如果在本地跑,可以用 `127.0.0.1`,`user_id` 也要换成你想要发送到的 QQ 号。具体的 API 列表见 [API 描述](/API)。如果需要使用 HTTPS 来访问,见 [HTTPS](https://github.com/richardchien/coolq-http-api/wiki/HTTPS)。 + +酷Q 收到的消息、事件会被 POST 到配置文件中指定的 `post_url`,为空则不上报。上报数据格式见 [上报数据格式](/Post)。 + +停用插件将会关闭 HTTP 线程,再次启用将重新读取配置文件。 + +除了 HTTP 方式,现在还支持 WebSocket 和反向 WebSocket 两种通信方式,它们的适用场景和使用方法见 [通信方式](/CommunicationMethods)。 + +另外,本插件所支持的 CQ 码在 [原生 CQ 码](https://docs.cqp.im/manual/cqcode/) 的基础上进行了一些增强,见 [CQ 码](/CQCode),并且支持以字符串或消息段数组格式表示消息,见 [消息格式](/Message)。 + +对于其它可能比较容易遇到的问题,见 [FAQ](https://github.com/richardchien/coolq-http-api/wiki/FAQ)。 + +### 使用 Docker + +如果你使用 Docker 来部署服务,可以直接运行已制作好的 Docker 镜像,例如: + +```bash +$ docker pull richardchien/cqhttp:latest +$ mkdir coolq # 用于存储 酷Q 的程序文件 +$ docker run -ti --rm --name cqhttp-test \ + -v $(pwd)/coolq:/home/user/coolq \ # 将宿主目录挂载到容器内用于持久化 酷Q 的程序文件 + -p 9000:9000 \ # noVNC 端口,用于从浏览器控制 酷Q + -p 5700:5700 \ # HTTP API 插件开放的端口 + -e COOLQ_ACCOUNT=123456 \ # 要登录的 QQ 账号,可选但建议填 + -e CQHTTP_POST_URL=http://example.com:8080 \ # 事件上报地址 + -e CQHTTP_SERVE_DATA_FILES=yes \ # 允许通过 HTTP 接口访问 酷Q 数据文件 + richardchien/cqhttp:latest +``` + +其中,`CQHTTP_POST_URL`、`CQHTTP_SERVE_DATA_FILES` 是用于配置插件运行的,格式为「`CQHTTP_` + 插件配置项的大写」,具体的配置项,见 [配置](/Configuration)。 + +然后访问 `http://<你的IP>:9000/` 进入 noVNC(默认密码 `MAX8char`),登录 酷Q,即可开始使用(插件已自动启用,配置文件也根据启动命令的环境变量自动生成了)。一般情况下,你不太需要关注插件是如何存在于容器中的。 + +API 描述、事件上报等文档,见前面「手动安装」一节提供的指引链接。 + +关于在 Docker 中使用本插件的更多细节,见 [Docker](/Docker)。 + +## 从旧版升级 + +由于 4.x 版本引入了一些不兼容的变化,因此这里给出一份 [升级指南](/UpgradeGuide),帮助用户从旧版升级到 4.x。 diff --git a/docs/4.13/Message.md b/docs/4.13/Message.md new file mode 100644 index 0000000..92251d2 --- /dev/null +++ b/docs/4.13/Message.md @@ -0,0 +1,123 @@ +# 消息格式 + +目前在发送、上报、回复消息时,全面支持两种消息格式:字符串(string)和数组(array)。 + +在上述三种情况中,「发送」指的是调用 API 直接发送消息(`message` 字段),「上报」指的是接收到消息之后向指定地址上报事件信息(`message` 字段),「回复」指的是上报事件时的响应中的快速回复(`reply` 字段)。 + +其中,发送和回复时,同时支持字符串和数组格式的消息,插件会自动识别相应字段的类型,比如下面两段 JSON 都是允许的: + +```json +{ + "message": "这是一条字符串格式的消息", + "others...": "..." +} +``` + +```json +{ + "message": [ + { + "type": "text", + "data": {"text": "这是第一段"} + }, + { + "type": "face", + "data": {"id": "111"} + }, + { + "type": "text", + "data": {"text": "这是表情之后的一段"} + } + ] +} +``` + +而上报消息时,会根据配置文件中指定的格式来上报,默认为字符串格式,具体请见 [配置文件说明](/Configuration) 的 `post_message_format` 项。 + +## 字符串格式 + +字符串格式是传统的消息格式,也是 酷Q 原生所使用的消息格式,无论纯文本还是图片、表情、链接分享等多媒体内容都放在同一个字符串中,即,一条消息对应一个字符串。 + +其中,多媒体内容使用 CQ 码来表示,形如 `[CQ:image,file=123.jpg]`,可以看出 CQ 码中包含一些特殊字符:`[`、`]`、`,` 等,而 CQ 码又是可能混杂在纯文本内容之中的,因此消息中的纯文本内容需要对特殊字符进行转义。关于 CQ 码的更多内容,见 酷Q 文档的 [CQ码](https://docs.cqp.im/manual/cqcode/),以及本文档的 [CQ 码](/CQCode) 部分。 + +## 消息段(广义 CQ 码) + +在介绍数组格式之前,先对 CQ 码的概念进行扩展。 + +狭义的 CQ 码是指字符串格式下用于表示多媒体内容的方式,形如 `[CQ:image,file=123.jpg]`,在阅读官方文档之后可以知道,这里 CQ 码「功能名」为 `image`,「参数」为 `file=123.jpg`,也即等号分隔的一个「键值对」。 + +要使传统的字符串格式能转换成数组格式或相反,必须要将狭义的 CQ 码用另外的可扩展的方式表示,而不再是和纯文本混杂在一起,因此引入「广义 CQ 码」的概念,或称「消息段」,后面为了避免混淆,将主要使用「消息段」来指「广义 CQ 码」、使用「CQ 码」来指「狭义 CQ 码」。 + +### 格式 + +消息段的基本格式如下(以 JSON 对象形式给出): + +```json +{ + "type": "image", + "data": { + "file": "123.jpg", + "url": "http://example.com/123.jpg" + } +} +``` + +其中 `type` 字段的类型为字符串,对应狭义 CQ 码中的「功能名」,`data` 字段的类型为对象,对应狭义 CQ 码的「参数」,此字段可为 null,其中的内容即为 CQ 码参数的「键值对」。**注意,所有「值」均使用字符串表示**。 + +**由于消息段不再将纯文本和多媒体内容放在一起,也就意味着任意一个字段的值都是真实值,而不再需要转义。** + +由此可以得出,任意 CQ 码都可以转换为一个消息段,任意消息段都可以转换成一个 CQ 码。 + +另外,为了使用消息段表示纯文本,引入一个「伪」CQ 码功能名 `text`,并在 `data` 中使用 `text` 字段来指示纯文本内容,例如: + +```json +{ + "type": "text", + "data": { + "text": "这是一段纯文本" + } +} +``` + +在将上面的消息段转成 CQ 码时,将会直接变成纯文本字符串,而不是真的转成 CQ 码。 + +## 数组格式 + +了解了「消息段」的概念之后,就不难理解消息的数组格式了,即消息段组成的数组。 + +例如,传统的字符串格式下的这样一条消息: + +``` +[第一部分][CQ:image,file=123.jpg]图片之后的部分,表情:[CQ:face,id=123] +``` + +表示成数组格式即为: + +```json +[ + { + "type": "text", + "data": { + "text": "[第一部分]" + } + }, + { + "type": "image", + "data": { + "file": "123.jpg" + } + }, + { + "type": "text", + "data": { + "text": "图片之后的部分,表情:" + } + }, + { + "type": "face", + "data": { + "id": "123" + } + } +] +``` diff --git a/docs/4.13/Post.md b/docs/4.13/Post.md new file mode 100644 index 0000000..37bcf1a --- /dev/null +++ b/docs/4.13/Post.md @@ -0,0 +1,413 @@ +# 事件上报 + +## 上报方式 + +当配置文件中 `post_url` 配置项不为空时(**无论 `use_http` 是什么**),会将 酷Q 收到的事件通过 HTTP POST 上报,数据以 JSON 格式表示。上报的请求头中会包含一个 `X-Self-ID` 头来表示当前正在上报的机器人 QQ 号,如: + +```http +POST / HTTP/1.1 +X-Self-ID: 123456 +``` + +如果 `secret` 配置项也不为空,则会在每次上报的请求头中加入 HMAC 签名,如: + +```http +POST / HTTP/1.1 +X-Signature: sha1=f9ddd4863ace61e64f462d41ca311e3d2c1176e2 +X-Self-ID: 123456 +``` + +签名以 `secret` 作为密钥,HTTP 正文作为消息,进行 HMAC SHA1 哈希,你的后端可以通过该哈希值来验证上报的数据确实来自 HTTP API 插件。HMAC 介绍见 [密钥散列消息认证码](https://zh.wikipedia.org/zh-cn/%E9%87%91%E9%91%B0%E9%9B%9C%E6%B9%8A%E8%A8%8A%E6%81%AF%E9%91%91%E5%88%A5%E7%A2%BC)。 + +### HMAC SHA1 校验的示例 + +#### Python + Flask + +```python +import hmac +from flask import Flask, request + +app = Flask(__name__) + +@app.route('/', methods=['POST']) +def receive(): + sig = hmac.new(b'', request.get_data(), 'sha1').hexdigest() + received_sig = request.headers['X-Signature'][len('sha1='):] + if sig == received_sig: + # 请求确实来自于插件 + pass + else: + # 假的上报 + pass +``` + +#### Node.js + Koa + +```js +const crypto = require('crypto'); +const secret = 'some-secret'; + +// 在 Koa 的请求 context 中 +ctx.assert(ctx.request.headers['x-signature'] !== undefined, 401); +const hmac = crypto.createHmac('sha1', secret); +hmac.update(ctx.request.rawBody); +const sig = hmac.digest('hex'); +ctx.assert(ctx.request.headers['x-signature'] === `sha1=${sig}`, 403); +``` + +## 上报数据格式 + +每次上报的数据中必有的一个字段是 `post_type`,数据类型为字符串,用来指示此次上报的类型,有如下三种: + +| 上报类型 | 说明 | +| ------- | --- | +| `message` | 收到消息 | +| `notice` | 群、讨论组变动等通知类事件 | +| `request` | 加好友请求、加群请求/邀请 | + +其它字段随上报类型不同而有所不同,下面将在事件列表的「上报数据」标题下一一给出。 + +某些字段的值是一些固定的值,在表格的「可能的值」中给出,如果「可能的值」为空则表示没有固定的可能性。 + +另外,每一次上报都有下面几个字段,后面不再列出。 + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | ---- | +| `time` | number (int64) | 事件发生的时间戳 | +| `self_id` | number (int64) | 收到消息的机器人 QQ 号 | + +关于上面的 `time` 字段,由于 酷Q 的某次更新中移除了消息事件的 `time` 参数,因此目前插件上报的数据中,`notice` 和 `request` 类型上报的 `time` 是 酷Q 原生给出的时间,而 `message` 类型的上报中的 `time` 是事件到达插件的时间,后者有可能和事件实际的发生时间有差别。 + +## 上报请求的响应数据格式 + +事件上报的后端可以在上报请求的响应中直接指定一些简单的操作,如快速回复、快速禁言等。如果不需要使用这个特性,返回 HTTP 响应状态码 204,或保持响应正文内容为空;如果需要,则使用 JSON 作为响应正文,`Content-Type` 响应头任意(目前不会进行判断),但设置为 `application/json` 最好,以便减少不必要的升级成本,因为如果以后有需求,可能会加入判断。 + +响应的 JSON 数据中,支持的操作随事件的不同而不同,会在后面的事件列表中的「响应数据」标题下一一给出。需要指出的是,**响应数据中的每个字段都是可选的**,只有在字段存在(明确要求进行操作)时,才会触发相应的操作,否则将保持对 酷Q 整体运行状态影响最小的行为(比如默认不拦截事件、不回复消息、不处理请求,具体的默认行为下面会给出)。 + +「响应数据」给出的表格中的「允许的值」表示该字段允许的数据值,如果你返回的值不在允许的值范围内,则会采用默认行为,「允许的值」为空表示不限制。 + +**每个事件都有一个共同的支持的操作,即 `block` 字段**,数据类型为 boolean,`true` 表示拦截事件(不再让后面的插件处理),否则表示忽略(不拦截),例如: + +```json +{ + "block": true +} +``` + +如果你在处理上报请求时,返回上面的 JSON 作为响应,则优先级在 HTTP API 之后的其它插件将不会再收到这个事件。 + +此 `block` 字段后面不再列出。 + +另外,`post_type` 为 `notice` 的上报请求,都只支持响应 `block` 字段,而不支持其它操作。 + +## 上报和回复中的数据类型 + +在下面对上报数据的描述中,「数据类型」使用 JSON 中的名字,例如 `string`、`number` 等。 + +特别地,数据类型 `message` 表示该参数是一个消息类型的参数。在上报数据中,`message` 的实际类型根据配置项 `post_message_format` 的不同而不同,`post_message_format` 设置为 `string` 和 `array` 分别对应字符串和消息段数组;而在上报请求的回复中,`message` 类型的字段允许接受字符串、消息段数组、单个消息段对象三种类型的数据。关于消息格式的更多细节请查看 [消息格式](/Message)。 + +## 事件过滤 + +如果需要对事件进行过滤,以减小后端的负担,请参考 [事件过滤器](/EventFilter)。 + +## 事件列表 + +### 私聊消息 + +#### 上报数据 + +| 字段名 | 数据类型 | 可能的值 | 说明 | +| ----- | ------- | ------- | ---- | +| `post_type` | string | `message` | 上报类型 | +| `message_type` | string | `private` | 消息类型 | +| `sub_type` | string | `friend`、`group`、`discuss`、`other` | 消息子类型,如果是好友则是 `friend`,如果从群或讨论组来的临时会话则分别是 `group`、`discuss` | +| `message_id` | number (int32) | - | 消息 ID | +| `user_id` | number (int64) | - | 发送者 QQ 号 | +| `message` | message | - | 消息内容 | +| `raw_message` | string | - | 原始消息内容 | +| `font` | number (int32) | - | 字体 | +| `sender` | object | - | 发送人信息 | + +其中 `sender` 字段的内容如下: + +| 字段名 | 数据类型 | 说明 | +| ----- | ------ | ---- | +| `user_id` | number (int64) | 发送者 QQ 号 | +| `nickname` | string | 昵称 | +| `sex` | string | 性别,`male` 或 `female` 或 `unknown` | +| `age` | number (int32) | 年龄 | + +需要注意的是,`sender` 中的各字段是尽最大努力提供的,也就是说,不保证每个字段都一定存在,也不保证存在的字段都是完全正确的(缓存可能过期)。 + +##### 示例 + +```json +{ + "time": 1515204254, + "post_type": "message", + "message_type": "private", + "sub_type": "friend", + "message_id": 12, + "user_id": 12345678, + "message": "你好~", + "raw_message": "你好~", + "font": 456, + "sender": { + "nickname": "小不点", + "sex": "male", + "age": 18 + } +} +``` + +下面的其它事件同这个类似,将不再给出。 + +#### 响应数据 + +| 字段名 | 数据类型 | 说明 | 默认情况 | +| ----- | ------- | --- | ------- | +| `reply` | message | 要回复的内容 | 不回复 | +| `auto_escape` | boolean | 消息内容是否作为纯文本发送(即不解析 CQ 码),只在 `reply` 字段是字符串时有效 | 不转义 | + +### 群消息 + +#### 上报数据 + +| 字段名 | 数据类型 | 可能的值 | 说明 | +| ----- | ------- | ------- | --- | +| `post_type` | string | `message` | 上报类型 | +| `message_type` | string | `group` | 消息类型 | +| `sub_type` | string | `normal`、`anonymous`、`notice` | 消息子类型,正常消息是 `normal`,匿名消息是 `anonymous`,系统提示(如「管理员已禁止群内匿名聊天」)是 `notice` | +| `message_id` | number (int32) | - | 消息 ID | +| `group_id` | number (int64) | - | 群号 | +| `user_id` | number (int64) | - | 发送者 QQ 号 | +| `anonymous` | object | - | 匿名信息,如果不是匿名消息则为 null | +| `message` | message | - | 消息内容 | +| `raw_message` | string | - | 原始消息内容 | +| `font` | number (int32) | - | 字体 | +| `sender` | object | - | 发送人信息 | + +其中 `anonymous` 字段的内容如下: + +| 字段名 | 数据类型 | 说明 | +| ----- | ------ | ---- | +| `id` | number (int64) | 匿名用户 ID | +| `name` | string | 匿名用户名称 | +| `flag` | string | 匿名用户 flag,在调用禁言 API 时需要传入 | + +`sender` 字段的内容如下: + +| 字段名 | 数据类型 | 说明 | +| ----- | ------ | ---- | +| `user_id` | number (int64) | 发送者 QQ 号 | +| `nickname` | string | 昵称 | +| `card` | string | 群名片/备注 | +| `sex` | string | 性别,`male` 或 `female` 或 `unknown` | +| `age` | number (int32) | 年龄 | +| `area` | string | 地区 | +| `level` | string | 成员等级 | +| `role` | string | 角色,`owner` 或 `admin` 或 `member` | +| `title` | string | 专属头衔 | + +需要注意的是,`sender` 中的各字段是尽最大努力提供的,也就是说,不保证每个字段都一定存在,也不保证存在的字段都是完全正确的(缓存可能过期)。尤其对于匿名消息,此字段不具有参考价值。 + +#### 响应数据 + +| 字段名 | 数据类型 | 说明 | 默认情况 | +| ----- | ------- | --- | ------- | +| `reply` | message | 要回复的内容 | 不回复 | +| `auto_escape` | boolean | 消息内容是否作为纯文本发送(即不解析 CQ 码),只在 `reply` 字段是字符串时有效 | 不转义 | +| `at_sender` | boolean | 是否要在回复开头 at 发送者(自动添加),发送者是匿名用户时无效 | at 发送者 | +| `delete` | boolean | 撤回该条消息 | 不撤回 | +| `kick` | boolean | 把发送者踢出群组(需要登录号权限足够),**不拒绝**此人后续加群请求,发送者是匿名用户时无效 | 不踢 | +| `ban` | boolean | 把发送者禁言 `ban_duration` 指定时长,对匿名用户也有效 | 不禁言 | +| `ban_duration` | number | 禁言时长 | 30 分钟 | + +### 讨论组消息 + +#### 上报数据 + +| 字段名 | 数据类型 | 可能的值 | 说明 | +| ----- | ------- | ------- | --- | +| `post_type` | string | `message` | 上报类型 | +| `message_type` | string | `discuss` | 消息类型 | +| `message_id` | number (int32) | - | 消息 ID | +| `discuss_id` | number (int64) | - | 讨论组 ID | +| `user_id` | number (int64) | - | 发送者 QQ 号 | +| `message` | message | - | 消息内容 | +| `raw_message` | string | - | 原始消息内容 | +| `font` | number (int32) | - | 字体 | +| `sender` | object | - | 发送人信息 | + +其中 `sender` 字段的内容如下: + +| 字段名 | 数据类型 | 说明 | +| ----- | ------ | ---- | +| `user_id` | number (int64) | 发送者 QQ 号 | +| `nickname` | string | 昵称 | +| `sex` | string | 性别,`male` 或 `female` 或 `unknown` | +| `age` | number (int32) | 年龄 | + +#### 响应数据 + +| 字段名 | 数据类型 | 说明 | 默认情况 | +| ----- | ------- | --- | ------- | +| `reply` | message | 要回复的内容 | 不回复 | +| `auto_escape` | boolean | 消息内容是否作为纯文本发送(即不解析 CQ 码),只在 `reply` 字段是字符串时有效 | 不转义 | +| `at_sender` | boolean | 是否要在回复开头 at 发送者(自动添加) | at 发送者 | + +### 群文件上传 + +**注意:仅群文件上传表现为事件,好友发送文件在 酷Q 中没有独立的事件,而是直接表现为好友消息,请注意在编写业务逻辑时进行判断。** + +#### 上报数据 + +| 字段名 | 数据类型 | 可能的值 | 说明 | +| ----- | ------ | ------- | ---- | +| `post_type` | string | `notice` | 上报类型 | +| `notice_type` | string | `group_upload` | 通知类型 | +| `group_id` | number (int64) | - | 群号 | +| `user_id` | number (int64) | - | 发送者 QQ 号 | +| `file` | object | - | 文件信息 | + +其中 `file` 字段的内容如下: + +| 字段名 | 数据类型 | 说明 | +| ----- | ------ | ---- | +| `id` | string | 文件 ID | +| `name` | string | 文件名 | +| `size` | number (int64) | 文件大小(字节数) | +| `busid` | number (int64) | busid(目前不清楚有什么作用) | + +### 群管理员变动 + +#### 上报数据 + +| 字段名 | 数据类型 | 可能的值 | 说明 | +| ----- | ------ | -------- | --- | +| `post_type` | string | `notice` | 上报类型 | +| `notice_type` | string | `group_admin` | 通知类型 | +| `sub_type` | string | `set`、`unset` | 事件子类型,分别表示设置和取消管理员 | +| `group_id` | number (int64) | - | 群号 | +| `user_id` | number (int64) | - | 管理员 QQ 号 | + +### 群成员减少 + +#### 上报数据 + +| 字段名 | 数据类型 | 可能的值 | 说明 | +| ----- | ------ | -------- | --- | +| `post_type` | string | `notice` | 上报类型 | +| `notice_type` | string | `group_decrease` | 通知类型 | +| `sub_type` | string | `leave`、`kick`、`kick_me` | 事件子类型,分别表示主动退群、成员被踢、登录号被踢 | +| `group_id` | number (int64) | - | 群号 | +| `operator_id` | number (int64) | - | 操作者 QQ 号(如果是主动退群,则和 `user_id` 相同) | +| `user_id` | number (int64) | - | 离开者 QQ 号 | + +### 群成员增加 + +#### 上报数据 + +| 字段名 | 数据类型 | 可能的值 | 说明 | +| ----- | ------ | -------- | --- | +| `post_type` | string | `notice` | 上报类型 | +| `notice_type` | string | `group_increase` | 通知类型 | +| `sub_type` | string | `approve`、`invite` | 事件子类型,分别表示管理员已同意入群、管理员邀请入群 | +| `group_id` | number (int64) | - | 群号 | +| `operator_id` | number (int64) | - | 操作者 QQ 号 | +| `user_id` | number (int64) | - | 加入者 QQ 号 | + +### 群禁言 + +#### 上报数据 + +| 字段名 | 数据类型 | 可能的值 | 说明 | +| ----- | ------ | -------- | --- | +| `post_type` | string | `notice` | 上报类型 | +| `notice_type` | string | `group_ban` | 通知类型 | +| `sub_type` | string | `ban`、`lift_ban` | 事件子类型,分别表示禁言、解除禁言 | +| `group_id` | number (int64) | - | 群号 | +| `operator_id` | number (int64) | - | 操作者 QQ 号 | +| `user_id` | number (int64) | - | 被禁言 QQ 号 | +| `duration` | number (int64) | - | 禁言时长,单位秒 | + +### 好友添加 + +#### 上报数据 + +| 字段名 | 数据类型 | 可能的值 | 说明 | +| ----- | ------ | -------- | --- | +| `post_type` | string | `notice` | 上报类型 | +| `notice_type` | string | `friend_add` | 通知类型 | +| `user_id` | number (int64) | - | 新添加好友 QQ 号 | + +### 加好友请求 + +#### 上报数据 + +| 字段名 | 数据类型 | 可能的值 | 说明 | +| ----- | ------ | -------- | --- | +| `post_type` | string | `request` | 上报类型 | +| `request_type` | string | `friend` | 请求类型 | +| `user_id` | number (int64) | - | 发送请求的 QQ 号 | +| `comment` | string | - | 验证信息(可能包含 CQ 码,特殊字符被转义) | +| `flag` | string | - | 请求 flag,在调用处理请求的 API 时需要传入 | + +#### 响应数据 + +| 字段名 | 数据类型 | 说明 | 默认情况 | +| ----- | ------- | --- | ------- | +| `approve` | boolean | 是否同意请求 | 不处理 | +| `remark` | string | 添加后的好友备注(仅在同意时有效) | 无备注 | + +### 加群请求/邀请 + +#### 上报数据 + +| 字段名 | 数据类型 | 可能的值 | 说明 | +| ----- | ------ | -------- | --- | +| `post_type` | string | `request` | 上报类型 | +| `request_type` | string | `group` | 请求类型 | +| `sub_type` | string | `add`、`invite` | 请求子类型,分别表示加群请求、邀请登录号入群 | +| `group_id` | number (int64) | - | 群号 | +| `user_id` | number (int64) | - | 发送请求的 QQ 号 | +| `comment` | string | - | 验证信息(可能包含 CQ 码,特殊字符被转义) | +| `flag` | string | - | 请求 flag,在调用处理请求的 API 时需要传入 | + +#### 响应数据 + +| 字段名 | 数据类型 | 说明 | 默认情况 | +| ----- | ------- | --- | ------- | +| `approve` | boolean | 是否同意请求/邀请 | 不处理 | +| `reason` | string | 拒绝理由(仅在拒绝时有效) | 无理由 | + +## 元事件 + +上面的事件列表是 酷Q 直接支持的、QQ 机器人真实接收到的事件,除了这些,插件自己还会产生一类事件,这里称之为「元事件」,例如生命周期事件、心跳事件等,这类事件与插件(以及 酷Q)本身的运行状态有关,而与 QQ 无关。 + +元事件的上报方式和普通事件完全一样,`post_type` 字段为 `meta_event`。 + +## 元事件列表 + +### 生命周期 + +**注意,目前生命周期元事件只有 HTTP 上报(配置了 `post_url`)的情况下可以收到,WebSocket 和反向 WebSocket 无法收到。** + +| 字段名 | 数据类型 | 可能的值 | 说明 | +| ----- | ------ | -------- | --- | +| `post_type` | string | `meta_event` | 上报类型 | +| `meta_event_type` | string | `lifecycle` | 元事件类型 | +| `sub_type` | string | `enable`、`disable` | 事件子类型,分别表示插件启用、插件停用 | + +### 心跳 + +心跳类型的元事件需要通过设置配置项 `enable_heartbeat` 为 `true` 开启,并可通过 `heartbeat_interval` 配置心跳间隔(单位毫秒)。 + +| 字段名 | 数据类型 | 可能的值 | 说明 | +| ----- | ------ | -------- | --- | +| `post_type` | string | `meta_event` | 上报类型 | +| `meta_event_type` | string | `heartbeat` | 元事件类型 | +| `status` | object | - | 状态信息 | +| `interval` | number (int64) | - | 到下次心跳的间隔,单位毫秒 | + +其中 `status` 字段的内容和 [`get_status` 接口的响应数据](/API#响应数据27) 相同。 diff --git a/docs/4.13/UpgradeGuide.md b/docs/4.13/UpgradeGuide.md new file mode 100644 index 0000000..0fabe9b --- /dev/null +++ b/docs/4.13/UpgradeGuide.md @@ -0,0 +1,42 @@ +# 升级指南 + +由于 4.x 版本相比 3.x 引入了一些破坏性更改,因此这里给出一份升级指南,帮助用户从旧版升级到 4.x。 + +## 事件上报的数据字段变更 + +这个变化破坏性比较大,如果不更改配置或代码,可能使当前可用的程序变得不可用。首先列出变更如下: + +- 群组消息中匿名信息现在以对象形式表示,例如 `"anonymous": {"id": 1000019, "name": "邓八公", "flag": "AAAAAAAPQlMABrXLsMu5qwAokaXsWulfxg2hPMTHguk1acbiU1NyW2BfxEnEMR5SNYFSns6SKKVe5A=="}`,非匿名消息中此字段为 `null` +- 通知类上报中(群成员增加、群管理员变更等),`post_type` 字段值从 `event` 变为 `notice`,原先的 `event` 字段变为 `notice_type` 字段 +- 请求类上报的 `message` 字段现变为 `comment` 字段 + +如果你是应用作者,可将使用到的发生了变化的地方字段的键值直接做相应修改,如果现有代码过于复杂不易修改,可开启 `enable_backward_compatibility` 配置项来临时保持兼容;对于 SDK 作者,建议同时兼容 4.x 和 3.x 两种上报,且接口也分别和上报对应,例如同时提供 `event.NoticeType` 和 `event.Event` 来分别表示 4.x 的 `notice_type` 和 3.x 的 `event` 字段,并在文档或注释中做相应说明,如果无法同时兼容,建议将 SDK 的接口写为 4.x 版本的样式,然后再通过将 3.x 的上报转换为 4.x 的格式来兼容。 + +## 事件过滤器的变更 + +变更如下: + +- 事件过滤器不再使用 `use_filter` 配置项来开关,而是使用 `event_filter` 直接指定过滤器规则文件的相对路径(相对于 `app\io.github.richardchien.coolqhttpapi`),默认为空,即表示不启用事件过滤器 +- 事件过滤器规则中,旧版中对消息原始文本进行过滤的 `message` 字段现在改为处理过的数组格式的消息,未经处理的原始消息文本现在保存在 `raw_message` 字段 + +如果在 3.x 版本时使用了过滤器,升级到 4.x 版本时,需要将配置文件中的 `use_filter=true` 改为 `event_filter=filter.json`,由于现在是直接指定过滤规则文件名,也意味着可以针对不同的 QQ 号应用不同的过滤规则。 + +除了配置项需要修改之外,如果过滤规则中对原来的 `message` 字段写了规则,则需要改成 `raw_message`,然后将上一节中提到的上报数据中发生了变更的字段也做修改,比如 `{"post_type": "event"}` 改为 `{"post_type": "notice"}`,需要注意的是,`enable_backward_compatibility` 配置项**不会**影响事件过滤器看到的数据。 + +## User-Agent 变更 + +插件发送请求时的 User-Agent 由形如 `CoolQHttpApi/3.4.0` 改成了形如 `CQHttp/4.0.0`。 + +## `/get_status` 接口返回数据的变更 + +`/get_status` 接口的返回数据有所变化,但 `good`、`online`、`app_enabled` 字段仍然不变,具体请自行测试。如果你的应用需要检测 酷Q 和 HTTP API 插件的运行状态,建议只使用上述三个字段来判断。 + +## Docker 镜像的变更 + +版本锁的文件名由原来的 `app.lock` 改为 `version.lock`,如果你需要解除容器中插件版本的锁定(即每次启动容器时都使用镜像对应版本的插件 cpk 文件覆盖已有的 cpk),现在需要删除 `version.lock`。此外,这个文件不再影响配置文件。 + +现在容器启动时会检查是否存在 `config` 目录,如果不存在,则会创建它,并从环境变量读取 `CQHTTP_` 开头的项,写入配置文件;如果存在,则默认情况下不做任何改变,除非 `FORCE_ENV` 环境变量为 `true`,则会完全删除现有的整个 `config` 目录,并根据环境变量重新写入。 + +## 运行时库的变更 + +由于新版使用了动态链接的 C 运行时,Windows 7 和 Windows Server 2008 等较老系统可能需要额外安装 [通用 C 运行库更新](https://support.microsoft.com/zh-cn/help/3118401/update-for-universal-c-runtime-in-windows) 才能正常使用,否则 酷Q 启动时会报 DLL 缺失错误。 diff --git a/docs/4.13/WebSocketAPI.md b/docs/4.13/WebSocketAPI.md new file mode 100644 index 0000000..2239f7f --- /dev/null +++ b/docs/4.13/WebSocketAPI.md @@ -0,0 +1,72 @@ +# WebSocket API 描述 + +**注:本页描述的是插件作为 WebSocket 服务端的情况,其它通信方式请见 [通信方式](/CommunicationMethods)。** + +除了 HTTP 方式调用 API、接收事件上报,目前插件还支持 WebSocket。使用 WebSocket 时,只需要你的机器人程序单方面的向插件建立连接,即可调用 API 和接收事件推送。数据全部使用 JSON 格式传递。 + +要使用 WebSocket,首先需要在配置文件中填写如下配置: + +```ini +ws_host = 0.0.0.0 # 监听的 IP +ws_port = 6700 # 监听的端口 +use_ws = yes # 启用 WebSocket 服务端 +``` + +重启插件后,便启动了 WebSocket 服务器。 + +插件提供了两个接口 `/api/` 和 `/event/`,分别用于调用 API 和推送事件。除此之外,还有 `/` 接口,用于在同一条连接上做上述两件事,这个接口相当于 `/api/` 和 `/event/` 的合并,下面不再单独说明。 + +如果配置文件中填写了 `access_token`,则建立连接时需要在请求头中加入验证头: + +```http +Authorization: Bearer kSLuTF2GC2Q4q4ugm3 +``` + +或者在 URI 中指定,如 `/api/?access_token=kSLuTF2GC2Q4q4ugm3`。 + +## `/api/` 接口 + +连接此接口后,向插件发送如下结构的 JSON 对象,即可调用相应的 API: + +```json +{ + "action": "send_private_msg", + "params": { + "user_id": 123456, + "message": "你好" + } +} +``` + +这里的 `action` 参数用于指定要调用的 API,具体支持的 API 可以参考 [API 列表](/API#api-列表)。`params` 用于传入参数,如果要调用的 API 不需要参数,则可以不加。 + +客户端向插件发送 JSON 之后,插件会往回发送一个调用结果,结构和 [响应说明](/API#响应说明) 是一样的,唯一的区别在于,调用 HTTP 接口时,通过 HTTP 状态码反应的错误情况,被移动到响应 JSON 的 `retcode` 字段,例如,HTTP 接口返回 404 的情况,对应到 WebSocket 的回复,是: + +```json +{ + "status": "failed", + "retcode": 1404, + "data": null +} +``` + +下面是 `retcode` 和 HTTP 接口的状态码的对照: + +| `retcode` | HTTP 接口中的状态码 | +| --------- | ----------------- | +| 1400 | 400 | +| 1401 | 401 | +| 1403 | 403 | +| 1404 | 404 | + +目前实际上 `1401` 和 `1403` 并不会真的返回,因为如果建立连接时鉴权失败,连接会直接断开,根本不可能进行到后面的接口调用阶段。 + +对于 `/api/` 接口,你可以保持连接,也可以每次请求是重新建立连接,区别不是很大。 + +## `/event/` 接口 + +连接此接口后,插件会在收到事件后推送至客户端,推送的格式和 HTTP POST 方式上报的完全一致,见 [上报数据格式](/Post#上报数据格式),事件列表见 [事件列表](/Post#事件列表)。 + +与 HTTP 上报不同的是,WebSocket 推送不会对数据进行签名(即 HTTP 上报中的 `X-Signature` 请求头在这里没有等价的东西),并且也不会处理响应数据。如果对事件进行处理的时候需要调用接口,请使用 HTTP 接口或 WebSocket 的 `/api/` 接口。 + +此外,这个接口和配置文件的 `post_url` 不冲突,如果开启了 WebSocket 支持,同时 `post_url` 也不为空的话,插件会先通过 HTTP 上报给 `post_url`,在处理完它的响应后,向所有已连接了 `/event/` 的 WebSocket 客户端推送事件。 diff --git a/docs/4.13/config.js b/docs/4.13/config.js new file mode 100644 index 0000000..277d7ca --- /dev/null +++ b/docs/4.13/config.js @@ -0,0 +1,64 @@ +let config = { + title: 'CoolQ HTTP API 插件文档', + home: 'Home.md', + repo: 'richardchien/coolq-http-api', + nav: [ + { + title: '首页', path: '/' + }, + { + title: 'Docker', path: '/Docker' + }, + { + title: '配置', path: '/Configuration' + }, + { + title: '通信方式', path: '/CommunicationMethods' + }, + { + title: 'API', type: 'dropdown', items: [ + { + title: 'API 描述', path: '/API' + }, + { + title: 'WebSocket API 描述', path: '/WebSocketAPI' + } + ] + }, + { + title: '事件', type: 'dropdown', items: [ + { + title: '事件上报', path: '/Post' + }, + { + title: '事件过滤器', path: '/EventFilter' + } + ] + }, + { + title: '消息内容', type: 'dropdown', items: [ + { + title: '消息格式', path: '/Message' + }, + { + title: 'CQ 码', path: '/CQCode' + } + ] + }, + { + title: '其它', type: 'dropdown', items: [ + { + title: '扩展', path: '/Extension' + }, + { + title: 'HTTPS', path: 'https://github.com/richardchien/coolq-http-api/wiki/HTTPS' + }, + { + title: 'FAQ', path: 'https://github.com/richardchien/coolq-http-api/wiki/FAQ' + } + ] + } + ], + tocVisibleDepth: 2, + plugins: [] +}; diff --git a/docs/4.13/index.html b/docs/4.13/index.html new file mode 100644 index 0000000..42aeb9e --- /dev/null +++ b/docs/4.13/index.html @@ -0,0 +1,22 @@ + + + + + + + CoolQ HTTP API 插件文档 + + + + +
+ + + + + + + + + + \ No newline at end of file diff --git a/docs/index.html b/docs/index.html index 1ce7c56..0273dd6 100644 --- a/docs/index.html +++ b/docs/index.html @@ -8,7 +8,7 @@