Skip to main content

事件处理

注册事件处理器

Mirai 对象的 on 方法用于注册事件处理器。

from mirai import GroupMessage

# 接收群消息
@bot.on(GroupMessage)
async def handle_group_message(event: GroupMessage):
print(str(event.message_chain)) # 打印消息内容

on 方法可以接受一个 Event 类型的子类,或字符串类型的事件名。

# 接收群消息
@bot.on(GroupMessage) # 或 @bot.on('GroupMessage')
async def handle_group_message(event: GroupMessage):
print(str(event.message_chain)) # 打印消息内容
tip

mirai.models.events 模块中找到更多事件类型。

事件处理器可以是同步的或异步的。

# 接收群消息
@bot.on(GroupMessage)
def handle_group_message_sync(event: GroupMessage):
print(str(event.message_chain)) # 打印消息内容

on 方法的第二个参数是 priority,用于指定事件处理器的优先级。值越小,优先程度越高。默认值为 0。

# 接收群消息
@bot.on(GroupMessage)
def handle_group_message(event: GroupMessage):
print(str(event.message_chain)) # 打印消息内容


@bot.on(GroupMessage, priority=1)
def handle_group_message_another(event: GroupMessage):
print('After handle_group_message') # 这句话会在消息内容之后打印
note

priority 参数曾经在 v0.1.3 被删除。v0.2.1 更新后,重新加入了 priority 功能。

事件处理器接受唯一的一个参数 event,它是一个 Event 类型的对象,包含了事件的相关信息。

生命周期

YiriMirai 提供了两个特殊的事件 StartupShutdown,用于在程序启动和关闭时进行相关操作。

YiriMirai 保证这两个事件触发时,机器人处于登录状态。因此,可以在处理这两个事件时调用 API。

@bot.on(Startup)
async def startup(_: Startup):
print(repr(bot.session_info.get()))

事件传播

事件传播指的是当一个事件被触发时,它所在的事件链的所有事件也会被触发。

当使用 Mirai 对象注册事件处理器时,事件传播使用的是继承事件链,一个事件会传播到它的父事件和祖先事件。例如,MessageEventFriendMessageGroupMessage 的父类,因此注册 MessageEvent 的事件处理器可以同时接收这两个事件。

from mirai import GroupMessage, FriendMessage, MessageEvent

@bot.on(GroupMessage)
async def handle_group_message(event: GroupMessage):
print("收到群消息。")

@bot.on(FriendMessage)
async def handle_friend_message(event: FriendMessage):
print("收到好友消息。")

@bot.on(MessageEvent)
async def handle_message_event(event: MessageEvent):
# 无论是群消息还是好友消息,这里都会被触发。
print(f"收到消息,类型为{event.type}。")

以下是 YiriMirai 定义的事件继承关系:

  • Event
    • BotEvent
      • BotOfflineEventActive
      • BotOfflineEventDropped
      • BotOfflineEventForce
      • BotOnlineEvent
      • BotReloginEvent
    • CommandEvent
      • CommandExecutedEvent
    • FriendEvent
      • FriendInputStatusChangedEvent
      • FriendNickChangedEvent
    • FriendRecallEvent
    • GroupEvent
      • BotGroupPermissionChangeEvent
      • BotJoinGroupEvent
      • BotLeaveEventActive
      • BotLeaveEventKick
      • BotMuteEvent
      • BotUnmuteEvent
      • GroupAllowAnonymousChatEvent
      • GroupAllowConfessTalkEvent
      • GroupAllowMemberInviteEvent
      • GroupEntranceAnnouncementChangeEvent
      • GroupMuteAllEvent
      • GroupNameChangeEvent
      • GroupRecallEvent
      • MemberCardChangeEvent
      • MemberHonorChangeEvent
      • MemberJoinEvent
      • MemberLeaveEventKick
      • MemberLeaveEventQuit
      • MemberMuteEvent
      • MemberPermissionChangeEvent
      • MemberSpecialTitleChangeEvent
      • MemberUnmuteEvent
    • MessageEvent
      • FriendMessage
      • GroupMessage
      • OtherClientMessage
      • StrangerMessage
      • TempMessage
    • NudgeEvent
    • RequestEvent
      • BotInvitedJoinGroupRequestEvent
      • MemberJoinRequestEvent
      • NewFriendRequestEvent
    • OtherClientEvent
      • OtherClientOnlineEvent
      • OtherClientOfflineEvent

你可以从 mirai.models.events 模块引入这些事件。部分常用的事件也可从顶层模块 mirai 的命名空间引入。

传播中止

如果想要阻止事件被其他事件处理器监听,或者想要阻止事件向上一级事件链传播,可以采用传播中止的方式。

YiriMirai 通过抛出异常实现传播中止。在 mirai.exceptions 模块中,定义了以下几个异常:

  • StopPropagation:终止事件处理器执行,并停止事件向上传播。
  • StopExecution:终止事件处理器执行,但不阻止事件向上传播。
  • SkipExecution:跳过同优先度的事件处理器,进入下一优先度。
note

传播中止将在 v0.2.4 中支持。

获取事件的信息

事件处理器接收唯一参数 event,它是一个 Event 类型的对象,包含了事件的相关信息。

一般来说,event 参数会传入一个 Event 的子类对象,具体类型与注册事件处理器时传入的事件类型相同。

YiriMirai 通过 pydantic 解析事件信息。Event 类型是 pydantic 的模型,可以从属性中获取事件信息。

例如:

@bot.on(Event)
async def handle_message_event(event: Event):
print(f"收到事件{event.type}。") # 获取事件名称

@bot.on(FriendMessage)
async def handle_friend_message(event: FriendMessage):
print("收到好友消息。",
f"来源:{event.friend.nickname}", # 获取好友昵称
f"来源qq号:{event.friend.id}", # 获取好友qq号
f"消息内容:{event.message_chain}" # 获取消息链
)

关于不同事件可用的属性,可以参考 mirai-api-http 的文档,或查看 YiriMirai 的 API 文档

快速响应

在事件处理器中,返回一个 API 调用的 corotine,即可快速响应。

@bot.on(FriendMessage)
def handle_friend_message(event: FriendMessage):
return bot.send_friend_message(event.sender.id, [Plain('Hello, World!')])

快速响应可以用于在同步的事件处理器中调用 API。

有的时候使用快速响应可以增强代码的可读性。

# 同意所有加好友申请
@bot.on(NewFriendRequestEvent)
def handle_new_friend_request(event: NewFriendRequestEvent):
return bot.resp_new_friend_request_event(
event_id=event.event_id,
from_id=event.from_id,
group_id=event.group_id,
operate=RespOperate.ALLOW,
message=''
)
tip

当只使用 WebHook Adapter 时,只能使用快速响应调用 API。