This repository has been archived by the owner on Aug 2, 2020. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 307
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
2,193 additions
and
1 deletion.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
# CQ 码 | ||
|
||
CQ 码的使用方式和 酷Q 原生的 CQ 码兼容(关于原生 CQ 码的使用,请看 [Pro/CQ码](https://d.cqp.me/Pro/CQ%E7%A0%81)),在要发送的消息中插入相应的代码即可,例如: | ||
|
||
``` | ||
[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)。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} | ||
``` |
Oops, something went wrong.