Skip to content

事件类型参考 ​

事件分四个体系:18 种接收事件(event/receive/,网关推送 + 2 个生命周期就绪事件)、28 种发送事件(event/send/,操作前触发、可取消)、28 种后置事件(event/send/,操作成功后触发、不可取消,与发送事件一一配对)与 3 种框架事件(event/ 根包,心跳与插件生命周期)。

事件层级 ​

Event (抽象基类,含 metadata 系统)
├── ReceiveEvent (抽象,携带 Session 快照)
│   ├── ReadyEvent                      # 每分片连接就绪(仅 WebSocket 模式,网关 READY)
│   ├── WebhookReadyEvent               # Webhook 回调服务就绪(仅 Webhook 模式,触发一次)
│   ├── ResumedEvent                    # 断线重连会话恢复(仅 WebSocket 模式)
│   ├── GroupMessageEvent               # 群普通消息
│   ├── GroupAtMessageEvent             # 群 @ 消息
│   ├── C2CMessageEvent                 # 私聊消息
│   ├── InteractionEvent                # 互动事件(按钮点击等)
│   ├── FriendAddEvent                  # 好友新增
│   ├── FriendDelEvent                  # 好友删除
│   ├── GroupAddRobotEvent              # 机器人被加入群
│   ├── GroupDelRobotEvent              # 机器人被移出群
│   ├── GroupMemberAddEvent             # 群成员增加
│   ├── GroupMemberRemoveEvent          # 群成员移除
│   ├── GroupMsgReceiveEvent            # 群消息接收开关:开启
│   ├── GroupMsgRejectEvent             # 群消息接收开关:关闭
│   ├── C2CMsgReceiveEvent              # 私聊消息接收开关:开启
│   ├── C2CMsgRejectEvent               # 私聊消息接收开关:关闭
│   └── GroupJoinRequestEvent           # 用户申请入群
├── SendEvent (抽象,可取消)
│   ├── GroupMessageSendEvent           # 群消息发送前
│   ├── C2CMessageSendEvent             # 私聊消息发送前
│   ├── C2CStreamMessageSendEvent       # 私聊流式消息发送前
│   ├── GroupFileSendEvent              # 群文件发送前(uploadGroupFile)
│   ├── C2CFileSendEvent                # 私聊文件发送前(uploadC2CFile)
│   ├── GroupUploadPrepareEvent         # 群分片预上传前
│   ├── GroupUploadPartFinishEvent      # 群分片确认前
│   ├── GroupUploadChunkedEvent         # 群分片合并前
│   ├── C2CUploadPrepareEvent           # 私聊分片预上传前
│   ├── C2CUploadPartFinishEvent        # 私聊分片确认前
│   ├── C2CUploadChunkedEvent           # 私聊分片合并前
│   ├── GroupMessageDeleteEvent         # 撤回群消息前
│   ├── C2CMessageDeleteEvent           # 撤回私聊消息前
│   ├── InteractionRespondEvent         # 互动响应前
│   ├── GroupMemberMuteEvent            # 群成员禁言前
│   ├── GroupMemberBatchRemoveEvent     # 批量移除群成员前
│   ├── GroupMemberBlacklistEvent       # 群黑名单操作前
│   ├── JoinRequestApproveEvent         # 入群申请批准前
│   ├── JoinRequestDeclineEvent         # 入群申请拒绝前
│   ├── UrlLinkGenerateEvent            # 分享链接生成前
│   ├── MenuUpdateEvent                 # C2C 菜单修改前
│   ├── PanelCreateEvent                # 指令面板创建前
│   ├── PanelUpdateEvent                # 指令面板修改前
│   ├── PanelDeleteEvent                # 指令面板删除前
│   ├── PanelTargetUpdateEvent          # 指令面板关联对象修改前
│   ├── MediaImagePrepareEvent          # 图片素材申请上传前
│   ├── MediaImageCompleteEvent         # 图片素材完成上传前
│   └── MediaImageDeleteEvent           # 图片素材删除前
│
├── NotifyEvent (抽象,不可取消 / 仅成功触发)
│   └─ 与上面 28 个 SendEvent 一一配对的 28 个 XxxNotifyEvent
│
├── HeartbeatEvent                     # 心跳发出 / 收到确认(仅 WebSocket)
├── PluginEnableEvent                  # 插件启用完成
└── PluginDisableEvent                 # 插件禁用完成

后置事件命名规则固定为前置事件名 + Notify,清单见 后置事件 一节。

ReceiveEvent 公共方法(会话快照) ​

所有接收事件在创建时对 Session 做只读快照,事件自带连接上下文:

方法返回类型说明
getSessionId()String会话 ID(断线重连恢复用,首连 READY 前为空串)
getLastSeq()int触发事件时的最后消息序列号
getIntent()int订阅事件的意图位掩码
getUrl()StringWebSocket 网关地址
getHeartbeatInterval()int心跳间隔(毫秒)
getShardId()int当前分片 ID(从 0 开始)
getShardCount()int总分片数(1 = 未分片)
nextReplySeq()int获取下一个被动回复序列号(原子操作,用于 msg_seq 去重)

分片

多分片时每个连接各自触发事件,用 getShardId() 区分来源。ReadyEvent 每片触发一次(仅 WebSocket 模式),全局初始化只在 getShardId() == 0 时做——插件做「机器人上线」初始化更推荐实现 Plugin.onActive()(两模式统一触发一次,无需判断分片)。

群消息事件 ​

GroupAtMessageEvent ​

用户 @机器人 时触发。事件名:GROUP_AT_MESSAGE_CREATE

方法返回类型说明
getId()String消息 ID(用于回复/撤回)
getAuthor()User发送者信息(可能为 null)
getContent()String文本内容(已去除 @ 前缀)
getGroupOpenid()String群 OpenID
getTimestamp()Timestamp事件时间
getMessageType()int0=普通, 3=结构化卡片, 101=并行消息, 102=聊天记录, 103=引用
getAttachments()List<MessageAttachment>附件列表
getMessageScene()MessageScene消息场景上下文(含 msg_idx 用于引用回复/去重)
getArkData()ARKData结构化卡片数据(message_type=3 时有值)
getMsgElements()List<MsgElement>消息元素列表(引用消息时有值)
getMentions()List<User>被 @ 的用户列表

User 记录 ​

群聊与单聊共用同一结构:单聊场景 userOpenid() 有值,群聊场景 memberOpenid() / memberRole() 有值。

java
public record User(
    String id,                // 用户唯一标识(OpenID 格式)
    String username,          // 昵称
    boolean bot,              // 是否机器人
    String unionOpenid,       // 跨应用统一 OpenID(可能为空)
    String unionUserAccount,  // 跨应用统一账号(可能为空)
    String userOpenid,        // 用户 OpenID(单聊场景)
    String memberOpenid,      // 群成员 OpenID(群聊场景)
    String memberRole         // 群内角色:member / admin / owner
) {}

author、mentions、MsgElement.author() 均为该类型。字段全部可能为 null,取值前先判空。

MessageAttachment 记录 ​

java
public record MessageAttachment(
    String url,            // 附件下载 URL
    String filename,       // 文件名
    int width,             // 宽(px),非图片为 0
    int height,            // 高(px),非图片为 0
    int size,              // 字节数
    String contentType,    // MIME 类型
    String voiceWavUrl,    // 语音转 WAV 的 URL
    String asrReferText    // 语音 ASR 识别文本
) {}

content_type 常见取值:voice(语音)、image/jpeg、image/png、image/gif、video/mp4、file(群文件)。

私聊消息事件 ​

C2CMessageEvent ​

事件名:C2C_MESSAGE_CREATE

方法返回类型说明
getId()String消息 ID
getAuthor()User发送者(单聊场景用 author().userOpenid())
getContent()String文本内容
getTimestamp()Timestamp事件时间
getMessageType()int消息类型
getAttachments()List<MessageAttachment>附件列表
getMessageScene()MessageScene消息场景上下文(含 msg_idx)
getArkData()ARKData结构化卡片数据
getMsgElements()List<MsgElement>消息元素列表

单聊回复的 openid

getAuthor() 可能为 null(服务端未下发作者信息时)。单聊场景取 userOpenid(),群场景取 memberOpenid():

java
User author = e.getAuthor();
if (author != null) {
    Bngeuit.replyC2CText(author.userOpenid(), e.getId(), 1, "收到私聊");
}

互动事件 ​

InteractionEvent ​

用户点击按钮、快捷菜单等时触发。必须调用 Bngeuit.respondInteraction() 响应,否则客户端一直 loading:

java
import cn.org.bukkit.bngeuit.Bngeuit;
import cn.org.bukkit.bngeuit.dto.message.interaction.InteractionResponseCode;
import cn.org.bukkit.bngeuit.event.SubscribeEvent;
import cn.org.bukkit.bngeuit.event.receive.InteractionEvent;

@SubscribeEvent
public void onInteraction(InteractionEvent e) {
    Bngeuit.respondInteraction(e.getId(),
        InteractionResponseCode.SUCCESS);

    // 按钮回调数据在 button_data
    if (e.isButtonClick() && "/confirm".equals(e.getButtonData())) {
        Bngeuit.sendGroupText(e.getGroupOpenid(), "已确认");
    }
}

常用方法:

方法返回类型说明
getId()String互动事件 ID(用于响应)
getType()InteractionType互动类型(按钮=11、快捷菜单=12 等)
getScene()InteractionScene场景(GROUP / C2C / GUILD)
getChatType()ChatType聊天类型(群=1、私聊=2)
getUserOpenid()String操作用户 OpenID
getGroupOpenid()String群 OpenID(群场景有值)
getButtonId()String被点击按钮 ID
getButtonData()String按钮回调数据(与创建按钮时一致)
isButtonClick()boolean是否为消息按钮点击(type=11)
isFromGroup()boolean是否来自群聊
getTimestamp()Timestamp触发时间
getMessageId()String被操作的消息 ID

完整方法列表

以上仅列出常用方法,完整方法列表请参阅 Javadoc 或源码 InteractionEvent.java。

好友与群管理 ​

事件触发时机
FriendAddEvent用户添加机器人为好友
FriendDelEvent用户删除机器人好友
GroupAddRobotEvent机器人被拉入群
GroupDelRobotEvent机器人被移出群
GroupMemberAddEvent新成员加入群
GroupMemberRemoveEvent成员退出群
GroupJoinRequestEvent用户申请入群

GroupJoinRequestEvent ​

用户申请入群时触发。事件名:GROUP_JOIN_REQUEST。机器人需拥有群管理员身份。

java
@SubscribeEvent
public void onJoinRequest(GroupJoinRequestEvent e) {
    // 批准入群
    Bngeuit.approveJoinRequest(e.getGroupOpenid(), e.getMemberOpenid(), e.getJoinRequestId());
    
    // 或拒绝入群
    Bngeuit.declineJoinRequest(e.getGroupOpenid(), e.getMemberOpenid(), 
        e.getJoinRequestId(), "不符合入群条件", false);
}
方法返回类型说明
getGroupOpenid()String群 OpenID
getMemberOpenid()String申请人 OpenID
getUnionOpenid()String申请人跨应用统一 OpenID
getUsername()String申请人昵称
getJoinRequestId()String申请 ID(用于传给审批 API)
getApplyAt()Timestamp申请时间
getApplySource()ApplySource申请来源:SELF_APPLY(直接申请)/ INVITED(被邀请)
getInvitedBy()String邀请人 OpenID(仅 INVITED 时有值)
isBot()boolean申请人是否为机器人
getRiskTips()StringQQ 安全系统风险提示
getVerifyInfo()VerifyInfo入群验证信息
getAutoApproved()AutoApproved自动审批信息(策略命中时有值)
isAutoApproved()boolean是否被自动审批策略通过

FriendAddEvent ​

用户添加机器人为好友时触发。事件名:FRIEND_ADD。author 字段不是消息事件里的 User——好友事件的 payload 只带 union_openid,因此独立为 FriendAuthor(dto.message.friend)。

方法返回类型说明
getOpenid()String用户 OpenID
getTimestamp()Timestamp添加时间
getScene()FriendAddScene添加来源场景枚举
getSceneParam()String来源场景参数
getAuthor()FriendAuthor用户信息(unionOpenid)
getUnionOpenid()String跨应用统一 OpenID(等价 getAuthor().unionOpenid())
getShortCode()String用户短 ID

FriendDelEvent 携带 getOpenid()、getTimestamp()、getAuthor()(FriendAuthor)与 getUnionOpenid()(等价 getAuthor().unionOpenid())。

系统事件 ​

  • ReadyEvent — 每个分片连接鉴权完成各触发一次(仅 WebSocket 模式,网关真实 READY)
  • WebhookReadyEvent — Webhook 回调服务启动完成后触发一次(仅 Webhook 模式,无伪造 ReadyEvent)
  • ResumedEvent — 断线重连(RESUME)成功(仅 WebSocket 模式)

插件推荐:onActive()

做「机器人已上线」的初始化(启动定时推送、上报在线状态等)时,推荐实现 Plugin.onActive():该生命周期在两种接入模式统一触发一次(WS 全部分片就绪 / Webhook 回调服务就绪),无需关心接入方式与分片,也无需自行防重。

发送事件(可取消) ​

所有发送事件实现 Cancellable,在 HTTP 调用前触发,取消则操作跳过、API 返回 null。常用字段示例(以 GroupMessageSendEvent 为例):

方法返回类型说明
getGroupOpenid()String目标群
getMsgType()MsgType消息类型
getContent()String文本内容
getMarkdown()MessageMarkdownMarkdown 负载
getKeyboard()Keyboard内嵌键盘
getCard()Card图文卡片
getMedia()MediaInfo富媒体信息
getMsgId()String被动回复的原消息 ID
getMsgSeq()int消息序号
getMessageReference()MessageReference消息引用
setCancelled(boolean)—取消本次操作

C2CStreamMessageSendEvent ​

私聊流式消息发送事件,字段使用枚举类型:

方法返回类型说明
getUserOpenid()String目标用户
getInputMode()InputMode输入模式(InputMode.APPEND / InputMode.REPLACE)
getContentType()StreamContentType内容类型(StreamContentType.TEXT / StreamContentType.MARKDOWN)
getContentRaw()String消息内容
getInputState()InputState输入状态(InputState.GENERATING / InputState.DONE)
getIndex()int分片序号,从 0 递增
getEventId()String被动回复事件 ID
getMsgId()String被动回复消息 ID
getStreamMsgId()String流式消息 ID(首片为空)
getMsgSeq()int消息序号
setCancelled(boolean)—取消该分片发送

InputState 枚举 ​

流式消息输入状态,用于 StreamMessageRequest 和 C2CStreamMessageSendEvent:

枚举值说明
GENERATING1生成中
DONE10生成结束

分片上传事件携带 File 对象:GroupUploadChunkedEvent.getFile() / getFileName() / getFilePath()。

GroupMemberMuteEvent ​

群成员禁言操作前触发。取消可阻止禁言操作。

方法返回类型说明
getGroupOpenid()String群 OpenID
getMembers()List<SetMemberMuteState>禁言设置列表(含 op、memberOpenid、muteExpireAt)

JoinRequestApproveEvent ​

批准入群申请前触发。取消可阻止批准操作。

方法返回类型说明
getGroupOpenid()String群 OpenID
getMemberOpenid()String申请人 OpenID
getJoinRequestId()String申请 ID

JoinRequestDeclineEvent ​

拒绝入群申请前触发。取消可阻止拒绝操作。

方法返回类型说明
getGroupOpenid()String群 OpenID
getMemberOpenid()String申请人 OpenID
getJoinRequestId()String申请 ID
getRejectReason()String拒绝理由
isAddToBlacklist()boolean是否加入黑名单

UrlLinkGenerateEvent ​

生成分享链接前触发。取消可阻止生成操作。

方法返回类型说明
getCallbackData()String回调数据(链接被点击时携带)

修改 C2C 自定义菜单前触发。取消可阻止修改操作。

方法返回类型说明
getMenu()Menu新菜单配置

PanelCreateEvent ​

创建指令面板前触发。取消可阻止创建操作。

方法返回类型说明
getScope()String生效场景("c2c" / "group")
getTargetType()String作用范围("all" / "specific")
getUserOpenids()List<String>关联用户列表(C2C + specific 时有效)
getGroupOpenids()List<String>关联群列表(group + specific 时有效)
getPanel()Panel面板配置

PanelUpdateEvent ​

修改指令面板前触发。取消可阻止修改操作。

方法返回类型说明
getPanelId()String面板 ID
getPanel()Panel新面板配置

PanelDeleteEvent ​

删除指令面板前触发。取消可阻止删除操作。

方法返回类型说明
getPanelId()String面板 ID

PanelTargetUpdateEvent ​

修改指令面板关联对象前触发。取消可阻止修改操作。

方法返回类型说明
getPanelId()String面板 ID
getRequest()PanelTargetRequest关联对象修改请求(含 op、userOpenids、groupOpenids)

GroupMemberBatchRemoveEvent ​

批量移除群成员前触发。取消可阻止本次移除。

方法返回类型说明
getGroupOpenid()String群 OpenID
getMemberOpenids()List<String>待移除的成员 member_openid 列表
isAddToMemberBlacklist()boolean是否同时加入群黑名单

GroupMemberBlacklistEvent ​

群黑名单操作(加入 / 移出)前触发。取消可阻止本次操作。

方法返回类型说明
getGroupOpenid()String群 OpenID
getOp()BlacklistOp操作类型(ADD / DEL)
getMemberOpenids()List<String>目标成员 openid 列表

MediaImagePrepareEvent ​

图片素材申请上传前触发。取消可阻止整个上传流程。

方法返回类型说明
getFileName()String文件名
getFileSize()long文件大小(字节)
getFormat()MediaImageFormat图片格式(即 content_type)
getMd5()String文件 MD5
getSha1()String文件 SHA1

MediaImageCompleteEvent ​

图片素材完成上传前触发。取消可阻止提交完成。

方法返回类型说明
getUploadId()String上传任务 ID
getMd5()String提交的 MD5(正常情况下等于直传返回的 ETag)

MediaImageDeleteEvent ​

删除图片素材前触发。取消可阻止删除。

方法返回类型说明
getImageId()String图片 ID

后置事件(Notify) ​

28 个后置事件与发送事件一一配对,统一继承 NotifyEvent(不继承 SendEvent)。触发条件、取消语义与通用用法见 事件系统概述 的「后置事件」一节。

前置事件后置事件响应类型
GroupMessageSendEventGroupMessageSendNotifyEventMessageResponse
C2CMessageSendEventC2CMessageSendNotifyEventMessageResponse
C2CStreamMessageSendEventC2CStreamMessageSendNotifyEventStreamMessageResponse
GroupFileSendEventGroupFileSendNotifyEventUploadResponse
C2CFileSendEventC2CFileSendNotifyEventUploadResponse
GroupUploadPrepareEventGroupUploadPrepareNotifyEventUploadPrepareResponse
GroupUploadPartFinishEventGroupUploadPartFinishNotifyEventEmptyResponse
GroupUploadChunkedEventGroupUploadChunkedNotifyEventUploadResponse
C2CUploadPrepareEventC2CUploadPrepareNotifyEventUploadPrepareResponse
C2CUploadPartFinishEventC2CUploadPartFinishNotifyEventEmptyResponse
C2CUploadChunkedEventC2CUploadChunkedNotifyEventUploadResponse
GroupMessageDeleteEventGroupMessageDeleteNotifyEventEmptyResponse
C2CMessageDeleteEventC2CMessageDeleteNotifyEventEmptyResponse
InteractionRespondEventInteractionRespondNotifyEventEmptyResponse
GroupMemberMuteEventGroupMemberMuteNotifyEventEmptyResponse
GroupMemberBatchRemoveEventGroupMemberBatchRemoveNotifyEventBatchRemoveMembersResponse
GroupMemberBlacklistEventGroupMemberBlacklistNotifyEventBlacklistOpResponse
JoinRequestApproveEventJoinRequestApproveNotifyEventEmptyResponse
JoinRequestDeclineEventJoinRequestDeclineNotifyEventEmptyResponse
UrlLinkGenerateEventUrlLinkGenerateNotifyEventUrlLinkResponse
MenuUpdateEventMenuUpdateNotifyEventMenuUpdateResponse
PanelCreateEventPanelCreateNotifyEventPanelCreateResponse
PanelUpdateEventPanelUpdateNotifyEventPanelUpdateResponse
PanelDeleteEventPanelDeleteNotifyEventEmptyResponse
PanelTargetUpdateEventPanelTargetUpdateNotifyEventEmptyResponse
MediaImagePrepareEventMediaImagePrepareNotifyEventMediaImagePrepareResponse
MediaImageCompleteEventMediaImageCompleteNotifyEventMediaImageCompleteResponse
MediaImageDeleteEventMediaImageDeleteNotifyEventEmptyResponse

取用方式 ​

每个后置事件都提供 getOriginal()(返回对应前置事件,带完整操作入参)与窄化后的 getResponse(),无需强转:

java
@SubscribeEvent
public void onSent(C2CMessageSendNotifyEvent e) {
    C2CMessageSendEvent original = e.getOriginal();
    MessageResponse resp = e.getResponse();      // 可能为 null(2xx 空体)
    if (resp != null) {
        log.info("已发送给 {},消息 ID={}", original.getOpenid(), resp.id());
    }
}

框架事件 ​

事件触发时机说明
HeartbeatEventWS 发出心跳包(op=1)或收到心跳确认(op=11)无载荷、不可取消,每周期两次;Webhook 模式永不触发
PluginEnableEvent插件 onEnable 完成并登记后getPlugin() 取插件实例,不可取消
PluginDisableEvent插件 onDisable 与资源清理完成后同上

这三个事件不属于 ReceiveEvent / SendEvent / NotifyEvent 体系,需按各自类型单独注册。