import { Channel } from 'koishi'
// 判断会话用户是否被设置了 ignore 状态
if (session.channel.flag & Channel.Flag.ignore) {}
// 为频道设置一个 ignore 状态
session.channel.flag |= Channel.Flag.ignore
// 为频道取消一个 silent 状态
session.channel.flag &= ~Channel.Flag.silent
内置用户系统
TIP
本节所介绍的内容需要你安装一个数据库支持。如果你暂时不打算使用数据库,那么可以略过。
在实际的机器人开发过程中,用户系统往往是必不可少的一环——它在展现机器人功能多样性的同时也避免了某个功能被滥用的情况。本章就来介绍 Koishi 内置的用户系统,以及用户数据是如何与指令调用相联系的。
数据结构
Koishi 内置了下面几个数据库字段:
- user: 用户表
- id:
string
内部编号 - name:
string
用户昵称 - ???:
string
平台编号 - flag:
number
状态标签 - authority:
number
用户权限
- id:
- channel: 频道表
- platform:
string
平台名 - id:
string
平台编号 - flag:
number
状态标签 - assignee:
string
代理者
- platform:
下面我们将分别介绍它们。
状态标签
Koishi 使用状态标签来管理用户和群的可能状态。状态标签是一个正整数,它的每一个二进制位表示一种可能状态的开启或关闭。在 Koishi 中,这些状态通过一个枚举类型来进行辨别和修改。以下是内置的状态标签列表:
- User.Flag.ignore: 不响应用户的任何消息
- Channel.Flag.ignore: 不响应频道内的任何消息
- Channel.Flag.silent: 不主动向频道发送任何消息
利用位运算操作符,你可以用下面的方法辨别和修改状态信息:
用户权限
Koishi 内部有一套默认的权限系统,它存储于用户数据的 authority
字段,并遵循下面的 核心规则:
- 数据库中没有的用户默认拥有 0 级权限
- 高权限者能够执行一切低权限者的操作
当我们调用 database.getUser()
这样的原始接口向数据库请求用户资料时,如果该用户不存在,则会返回 undefined
;但当我们调用 session.getUser()
这样的高级接口时,如果该用户不存在,则返回一个默认的 0 级用户对象而不是 null
。这种特性能够尽可能减少用户存在性的判断代码——我们认为任何账号都是存在于数据库的,只不过有些是 0 级而已。
在此基础上,我们还扩充出了这样的一套 设计准则:
- 0 级:不存在的用户
- 1 级:所有用户,只能够接触有限的功能
- 2 级:高级用户,能够接触几乎一切机器人的功能
- 3 级:管理员,能够直接操作机器人事务
- 4 级:高级管理员,能够管理其他账号
这套准则被用于 Koishi 的所有官方包的指令中,但是你也可以手动进行更改,扩展出你所需要的权限系统。稍后,我们将看到这些权限是如何被用于指令调用的。
平台相关字段
Koishi v3 起支持多平台和多账户,因此在用户系统中也需要记录相关的信息。
用户数据中有一个可变字段,它记录了你在特定平台上的 用户编号。例如,如果你的 QQ 号的 111222333,Telegram 号为 444555666,那么你的用户数据可能长这样:
{
"id": 233,
// 请注意:即使 QQ 号都是数字,这个字段的值也永远是字符串
"onebot": "111222333",
"telegram": "444555666",
"flag": 0,
...
}
频道数据的 id
字段被称为 频道标识符,它由 平台名 和 频道编号 两部分组成,中间由冒号分隔。例如,一个群号为 123456789 的 QQ 群的频道标识符为 onebot:123456789
。
频道数据的 assignee
字段被称为 代理者,其中存储了负责该频道的机器人在对应平台的用户编号。当这个值与一个机器人无法匹配时,Koishi 会限制该机器人对该频道内信息的处理。这听起来可能有点奇怪,不过请想象一下当你的多个机器人同时加了一个频道时,一旦稍有不慎就可能导致这些机器人多次响应同一个输入,甚至可能导致循环触发等严重的后果。
当然,即使机器人的用户编号与频道的代理者编号不匹配,通过 @ 机器人的方式调用指令仍然是安全的和被 Koishi 允许的。代理者机制可以确保 Koishi 管理的同源机器人中同时最多只有一个会响应来自其所在群的信息。
自动注册数据
前面已经介绍过了,默认情况下每一名用户都是 0 级权限,每一个群都没有代理者,这虽然安全但也给 Koishi 的搭建带来了不小的麻烦。因此,我们也提供了自动注册的配置项:autoAuthorize
和 autoAssign
。下面展示两个例子:
# 一旦收到来自未知频道的消息,就自动注册频道数据,代理者为收到消息的人
autoAssign: true
# 一旦收到来自未知用户的消息,就自动注册用户数据,权限等级为 1
autoAuthorize: 1
export default {
// 为频道 123456789 自动分配代理者
autoAssign: ses => ses.channelId === '123456789',
// 为用户 987654321 设置 4 级权限
// 如果收到了来自未知用户的群消息,那么就自动注册用户数据,权限等级为 1
autoAuthorize: ses => ses.userId === '987654321' ? 4 : ses.groupId ? 1 : 0,
}