@koishijs/plugin-adapter-onebot

WARNING

尽管 Koishi 使用了 MITopen in new window 协议,但 OneBot 相关框架普遍使用了基于 AGPL 3.0open in new window 的协议。因此如果你使用 @koishijs/plugin-adapter-onebot 运行你的机器人,你将可能受到 AGPL 3.0 协议的限制,必须将你的代码开源并保持同协议。Koishi 及其作者对使用上述框架或违反上述限制的行为所可能造成的一切后果概不负责。

OneBotopen in new window 是一个聊天机器人应用接口标准,目前可用于 QQ 聊天机器人的实现。你可以使用下列实现该协议的框架:

我们推荐使用 go-cqhttp。在本文的后续部分我们只会介绍 go-cqhttp 的使用方法。有对其他框架感兴趣的同学也可以自行探索。

与此同时,OneBot 协议规定了四种不同的通信方式:

  • 正向 HTTP:OneBot 作为 HTTP 服务端,提供 API 调用服务
  • 反向 HTTP:OneBot 作为 HTTP 客户端,向用户配置的 URL 推送事件,并处理用户返回的响应
  • 正向 WebSocket:OneBot 作为 WebSocket 服务端,接受用户连接,提供 API 调用和事件推送服务
  • 反向 WebSocket:OneBot 作为 WebSocket 客户端,主动连接用户配置的 URL,提供 API 调用和事件推送服务

我们推荐使用正向 WebSocket,这种通信方式操作简便,且拥有相对较高的性能。在本文的后续部分我们将介绍每一种通信方式的配置方法。

安装与运行

  1. 首先从 这个页面open in new window 下载并解压最新版本的 go-cqhttp
  2. 打开命令行并 cd 到你的解压目录
  3. 输入 ./go-cqhttp 并运行,此时将提示:
未找到配置文件,正在为您生成配置文件中!
请选择你需要的通信方式:
  1: HTTP 通信
  2: 正向 WebSocket 通信
  3: 反向 WebSocket 通信
你的选择是: 2           # 根据你的需求可作更改,输入后回车进入下一步
默认配置文件已生成,请修改 config.yml 后重新启动。
  1. 根据 配置参考 中的说明修改 config.yml 文件。之后再次输入 ./go-cqhttp 并运行:
[INFO]: 登录成功 欢迎使用: balabala
  1. 如出现需要认证的信息, 请自行认证设备。

快速启动

默认情况下启用 go-cqhttp 将会有五秒钟的延时,可以使用命令行参数 faststart 进行跳过:

./go-cqhttp faststart

获取更新

除了直接用前面的方法下载新版本并替换原文件外,go-cqhttp 还提供了另一种获取更新的方式。

在命令行中进入 go-cqhttp 所在目录并输入:

./go-cqhttp update

如果在国内连接 GitHub 下载速度可能很慢, 可以使用镜像源下载:

./go-cqhttp update https://github.rc1844.workers.dev

几个可用的镜像源:

  • https://hub.fastgit.xyz
  • https://github.bajins.com
  • https://github.rc1844.workers.dev

安装 FFmpeg

为了支持任意格式的语音发送, 你需要安装 FFmpeg。

Windows

点击这里open in new window 下载并解压, 并为 bin 这个文件夹添加环境变量。

如果遇到下载速度缓慢的问题可以用 这个源open in new window

Ubuntu / Debian

在终端执行:

apt install -y ffmpeg

Fedora / RHEL / CentOS

在终端执行:

# Centos7 及之前
yum install ffmpeg ffmpeg-devel

# CentOS8 及之后
dnf install ffmpeg ffmpeg-devel

机器人选项

options.protocol

  • 可选值: http, ws, ws-reverse

要使用的协议类型。

options.token

  • 类型:string

发送信息时用于验证的字段。

options.endpoint

  • 类型:string

如果使用了 HTTP,则该配置将作为发送信息的服务端;如果使用了 WebSocket,则该配置将作为监听事件和发送信息的服务端。

options.proxyAgent

请求时默认使用的网络代理。

适配器选项

options.path

  • 类型:string
  • 默认值:'/onebot'

服务器监听的路径。仅用于 HTTP 通信方式。

options.secret

  • 类型:string

接收信息时用于验证的字段,应与 OneBot 的 secret 配置保持一致。

go-cqhttp 配置参考

首先下面的配置是与通信方式无关的:

config.yml
account:
  uin: 123456     # 必填,QQ 账号
  password: ''    # 推荐,密码为空时将使用扫码登录

下面介绍不同的通信方式所需的配置,以及 koishi.yml 的对应配置。

HTTP

config.yml
servers:
  - http:
      host: 127.0.0.1
      port: 5700
      post:
        - url: http://localhost:8080/onebot
          secret: my-secret
koishiyamlts

正向 WebSocket

config.yml
servers:
  - ws:
      host: 127.0.0.1
      port: 6700
koishiyamlts

反向 WebSocket

config.yml
servers:
  - ws-reverse:
      universal: ws://127.0.0.1:8080/onebot
koishiyamlts

配置 pathselfUrl

config.yml
servers:
  # 这里同时列出了 http 和 ws-reverse 中需要做的修改
  # 实际情况下你可能只需要用到其中一份配置
  - http:
      post:
        - url: https://my-host:9090/onebot
  - ws-reverse:
      universal: wss://my-host:9090/onebot
koishiyamlts

内部 API

你可以通过 bot.internalsession.onebot 访问到内部 API,参见 调用机器人

下面展示了目前已经实现的 API 列表。如要了解细节请自行点击对应方法的链接进行查阅。

OneBot v11 标准 API

注释:

  1. 这个方法只有三个参数,其中第二个参数对应 anonymousflag
  2. 这些方法并未被 go-cqhttp 支持,访问时可能出错

go-cqhttp 扩展 API

注释:

  1. 这个方法名与 go-cqhttp 一致,并不是拼写错误
  2. 原文为「单项」,此处保持一致

QQ 频道 API meta

使用异步调用

OneBot 提出了 异步调用 的概念,当 OneBot 服务器受到异步调用请求时,如果调用正确,将直接返回 200。这样做的好处是,如果某些操作有较长的耗时(例如发送含有大量图片的消息或清空数据目录等)或你不关心调用结果,使用异步调用可以有效防止阻塞。下面说明了异步调用和普通调用的关系:

async-method

但是另一方面,你也无法得知异步调用是否成功被执行。与此同时,没有副作用的异步调用也毫无意义(因为这些调用本身就是为了获取某些信息,但是异步调用是无法获取调用结果的)。因此,Koishi 为除此以外的所有异步调用都提供了 API,它们的调用接口与非异步的版本除了在方法后面加了一个 Async 外没有任何区别:

// 普通版本
const messageId = await session.onebot.sendPrivateMsg('123456789', 'Hello world')

// 异步版本,无法获得调用结果
await session.onebot.sendPrivateMsgAsync('123456789', 'Hello world')

TIP

虽然异步调用方法的名字以 Async 结尾,但是其他方法也是异步函数,它们都会返回一个 Promise 对象。取这样的名字只是为了与 OneBot 保持一致。

常见问题

我不知道应该下载 release 中的哪一个文件。

在终端执行:

node -e "console.log(process.arch)"

然后根据输出结果决定你要下载的文件的后缀部分:

  • x32: 386
  • x64: amd64
  • arm64: arm64
  • arm: armv7

我的 go-cqhttp 初次启动时并没有生成 config.yml。

请检查你的 go-cqhttp 是否为最新版本。

使用 HTTP 或反向 WebSocket 时无法接收消息,同时 go-cqhttp 有报错。

请检查你的配置是否正确。尤其注意以下几点:

  • koishi.yml 中的 selfId 必须写并且必须是字符串
  • 如果你使用 HTTP:请不要忘记配置 post,同时默认情况下 post 的 url 字段应该包含 /onebot
  • 如果你使用反向 WebSocket:默认情况下 universal 字段应该包含 /onebot

发送消息时提示「账号可能被风控」。

以下内容摘自 Mrs4s/go-cqhttp#211open in new windowMrs4s/go-cqhttp#633open in new window

风控也是分种类的,有 xml 消息被风控,有 json 消息被风控,也有发消息全部被风控。官方客户端正常那可以尝试更换 device.json 文件。再次声明,风控是随机事件,有人挂三五个月都不会被风控,有人天天被风控。是否风控由腾讯根据网络环境,设备,发送的消息来判断。

这里留下几个建议:

  • 不要在短时间内进行批量操作
  • 不要在新设备登录不久发长信息 / xml / json 信息,以 100 字内的信息最佳
  • 不要过分使用敏感操作

为什么其他平台的适配器名字都与平台一致,只有 QQ 对应 OneBot?

这是由多方原因共同导致的。

首先,许多平台都公开了自己的机器人接口,只有腾讯官方对机器人采取封杀的态度。因此只有 QQ 的适配器是基于第三方协议实现的,OneBot 正是这个协议的名字。而第三方协议远远不止一个,所以不应该用 QQ 这个笼统的名称。在未来也可能出现其他面向 QQ 的适配器。

反过来,OneBot 作为一个协议,未来也可能支持更多的聊天平台。届时只需有 @koishijs/plugin-onebot,Koishi 也相当于支持了这些平台。一旦出现了这样的情况,用 QQ 作为适配器名反而显得以偏概全了,这也是不妥当的。

但尽管这么说,从目前来看,当我们在讨论用 Koishi 实现 QQ 机器人时,都默认采用这个协议。