开发入门篇 /03/ 事件系统
概述
事件系统,就是在程序收到某种信号,比如收到消息、机器人上线下线等等的时候,通知已经注册监听器的程序,让它们对此作出反应。
所以,在实现机器人功能这一方面,事件系统非常重要。基本做法就是靠事件系统来处理用户发送的消息。
事件通道
要注册事件监听器,首先要获取一个事件通道 (EventChannel)。
现在我们要做的,是选一个合适的情景,获取一个事件通道,并将它存到一个变量里以便复用。
获取事件通道、监听事件的代码均写在插件启用、加载的地方。若只使用 mirai-core 开发,则保证写在机器人登录之前即可。
公共事件通道
公共事件通道 (GlobalEventChannel) 可以接收当前 mirai 已登录的所有机器人的消息。
以下代码支持链式调用
// kotlin
val channel = globalEventChannel()
// java,无法使用 globalEventChannel(), 可以用以下方法代替
EventChannel channel = GlobalEventChannel.INSTANCE.parentScope(this);
指定携程上下文和限制作用域
上面的代码中 .parentScope(this)
是限制消息通道的作用域。作用域很有用,当插件被停用时,插件的协程作用域也会被关闭,事件监听就会被同步停止。mirai-console 插件主类继承了 CoroutineScope
,故可填入 this
作为参数。
非特殊情况下建议指定事件通道的携程上下文和限制作用域。
机器人消息通道
如果你只想接收单独机器人的事件,请使用以下代码
// kotlin
val channel = bot.eventChannel
// java
EventChannel channel = bot.getEventChannel();
其中 bot
实例可以通过 Bot.getInstance
或 Bot.getInstanceOrNull
等途径获得,但需要注意的是这个方法只能获得已登录的机器人,也就是说在执行这两个方法的时候,机器人必须要已经登录了。
还记得 部署开发环境 中提到的 PostStartupExtension
吗?你可以注册这个钩子,将获取事件通道和注册监听器的代码写里面,就能保证在获取事件通道时,自动登录已完成了。且可以保证事件监听器只被注册一次
或者,我们可以换一种思路。
过滤
提示
没有特殊需要的话你可以跳过这部分,对你后续的开发没有影响。
在原来的事件通道的基础上,加上
.filterIsInstance<事件类>()
只监听某类事件,比如BotEvent
。默认情况下,所有事件都可以监听.filter(e -> 条件)
或.filter { 条件 }
根据条件过滤事件
示例如下
// kotlin
val channel = /*此处省略*/
.filterIsInstance<BotEvent>()
.filter { it.bot.id == 2431208142L }
// java
EventChannel channel = /*此处省略*/
.filterIsInstance(BotEvent.class)
.filter(event -> event.getBot().getId() == 2431208142L);
均为只接收机器人 2431208142 收到的机器人事件。
监听事件
获取好事件通道后,我们把它存到了一个变量 channel
里,接下来,我们将正式使用事件通道注册监听器,实现机器人功能。
提示
别急,你先别急