amesu
v2.2.0
Published
Node.js SDK for QQ Bot.
Downloads
50
Readme
本项目是一个在 Node.js 环境下运行的 QQ 机器人第三方 SDK。
Introduction
由于腾讯是近期上线的群聊 API,官方文档的内容与实际表现有部分差异,请勿将其用于生产环境。
项目的名字来源于 Cygames 开发和发行的游戏『公主连结 Re:Dive』中的登场角色「アメス」,其罗马音 「a me su」 用作了本项目的名字。
Install
npm i amesu
Usage
const { Client } = require('amesu');
const client = new Client({
appid: '1145141919',
token: '38bc73e16208135fb111c0c573a44eaa',
secret: '6208135fb111c0c5',
events: ['GROUP_AND_C2C_EVENT', 'PUBLIC_GUILD_MESSAGES'],
});
// 监听频道消息
client.on('at.message.create', async event => {
// 快捷回复
await event.reply({
content: 'hello world',
});
});
// 监听群聊消息
client.on('group.at.message.create', async event => {
// API 调用
await client.api.sendGroupMessage(event.group_openid, {
msg_id: event.id,
msg_type: 0,
content: 'hello world',
});
});
// 机器人上线
client.online();
事件回调中的 reply()
函数是 client.api
的语法糖,会根据消息事件的类型指向对应消息发送的 api 函数,并自动传入 from_id 与 msg_id。
Event
目前 socket 返回的事件全部为大写,并用下划线做分割。但是在 Node.js 的 EventEmitter
中,事件名一般使用小写字母。
这是因为事件名通常表示一种行为或状态,而不是一个特定的类或构造函数。根据 JavaScript 的命名约定,使用小写字母来表示这些行为或状态更为常见和推荐。
所以 Amesu 针对事件名做了以下处理:
- 事件名全部转换为小写
- 使用小数点替换下划线
- 会话事件添加
session
前缀
例如 MESSAGE_CREATE
-> message.create
,READY
-> session.ready
。
你可以仅监听事件的部分前缀,例如:
const { Client } = require('amesu');
const client = new Client();
client
.on('guild.member', event => {
console.log(event);
})
.online();
这样 guild.member.add
、guild.member.update
、guild.member.remove
,三个事件将会被全部监听,这使得消息订阅更具有灵活性。
Config
/** 客户端配置项 */
interface ClientConfig {
/** 机器人 ID */
appid: string;
/** 机器人令牌 */
token: string;
/** 机器人密钥 */
secret: string;
/** 订阅事件 */
events: IntentEvent[];
/** 是否开启沙盒,默认 `false` */
sandbox: boolean;
/** 掉线重连数,默认 `3` */
max_retry?: number;
/** 日志等级,默认 `'INFO'`,仅输出收到的指令信息 */
log_level?: LogLevel;
}
/** 日志等级,具体使用可查阅 log4js 文档 */
type LogLevel = 'OFF' | 'FATAL' | 'ERROR' | 'WARN' | 'INFO' | 'DEBUG' | 'TRACE' | 'ALL';
API
Client.api
封装了官方文档所提供的 api 接口,可直接调用。(并不是所有 api 都能返回期望的结果)
Client.request
基于 fetch 封装,可发送自定义网络请求。
Client.online()
机器人上线。
Client.offline()
机器人下线。
Client.useEventInterceptor(interceptor)
添加事件拦截器。
Request.useRequestInterceptor(interceptor)
添加请求拦截器。
Request.useResponseInterceptor(interceptor)
添加响应拦截器。
Request.basis(config)
发送网络请求。(基础封装)
Request.get(url[, params][, config])
发送 GET 请求。
Request.delete(url[, params][, config])
发送 DELETE 请求。
Request.post(url[, params][, config])
发送 POST 请求。
Request.put(url[, params][, config])
发送 PUT 请求。
Request.patch(url[, params][, config])
发送 PATCH 请求。
插件开发
Amesu 仅仅是一个用于帮助建立 socket 通信的 SDK,而不是一个机器人解决方案,这两者不应该耦合,所以并未原生提供插件支持。
如果你想要开发插件,建立属于自己的生态,可以直接将她作为依赖进行二次开发。她十分的轻便,没有复杂的依赖项。拥有完整类型提示的同时,仅有 120 kb 的大小,而官方 SDK 却占据了 430 kb+。
若不想手搓,可以使用 kokkoro 框架进行机器人开发。如果不想集成框架体系,那么你也可以直接安装 @kokkoro/core
依赖去自定义插件。
npm i @kokkoro/core
插件代码示例:
import { useCommand, useEvent } from '@kokkoro/core';
/**
* @type {import('@kokkoro/core').Metadata}
*/
export const metadata = {
name: 'example',
description: '插件示例',
};
export default function Example() {
useEvent(
ctx => {
ctx.logger.mark('link start');
},
['session.ready'],
);
useCommand('/测试', () => 'hello world');
useCommand('/复读 <message>', ctx => ctx.query.message);
}
更多示例可查看 core 的 README 自述。
FAQ
为什么要做这个项目?
因为官方 频道 SDK 已经有 2 年没更新了,不支持群聊而且使用体验非常糟糕。
为什么 config 一定要指定 events?
如果你是公域机器人,那么在使用官方 SDK 不传入 events 情况下,就会不断重连并在控制台疯狂输出。
原因是部分事件仅限私域机器人使用,如果公域机器人订阅了就会抛异常,私域机器人订阅了公域事件却不会有任何问题...
官方 SDK 的逻辑是没有传 events 就默认监听全部事件(其实也并不是全部,文档里有遗漏),这是不合理的。现在也没有任何手段知道机器人是公域还是私域,以及是否拥有群聊权限等问题,因此只能手动在 config 传入。
为什么部分 API 没有返回结果?
腾讯是近期才开放群聊 API 内测的,提供的文档也很不完善,目前存在字段、返回结果不一致,v1、v2 接口混用(鉴权方式不一样)等问题,所以调用某些接口可能会无法达到预期。
为什么 request 不使用 axios 封装?
axios 太大了,基于 fetch 的封装 build 后大小仅 3 kb 不到,基本满足大部分的使用场景。如果你想要使用 axios 或者其它网络请求库,可以自行安装依赖。
这个 SDK 能做什么?
频道与群聊的消息收发已测试完毕,API 返回结果与 interface 不符的问题还待腾讯后续完善文档和接口统一。
当前 Amesu 已经有了完整的鉴权流程(会话保活、掉线重连、凭证刷新),并做了日志和网络请求的封装,后面没什么问题就不会再有大改了。如果有 API 缺失,在 api
文件内参考格式直接添加 url 就可以正常使用,也欢迎来提 pr。