跳到主要内容

机器人事件

机器人事件用于监听即时通讯平台(如QQ)的消息和状态变化,包括群消息、私聊消息、群成员变动等。这些事件是实现机器人功能的核心接口。

基础事件类

EasyEvent

所有事件的基类,包含适配器相关信息。

declare class EasyEvent {
IsCanceled: boolean; // 事件是否已被取消
AdapterName: string; // 适配器名称(onebot11)
AdapterPlatform: string; // 适配器平台名称(qq)
AdapterContext: IAdapterContext; // 适配器操作上下文
}

属性说明

  • IsCanceled: 如果设置为true,EasyBot内部的处理器将不响应此次事件
  • AdapterName: 适配器名称,如"onebot11"
  • AdapterPlatform: 适配器平台名称,如"qq"
  • AdapterContext: 适配器操作上下文,提供各种API调用

事件分类

统一封装接口

EasyBot 提供统一的事件接口,所有适配器(如 OneBot、Lagrange 等)都实现这些标准接口。

高级接口

提供原生消息事件,用于实现 EasyBot 未封装的高级功能。

事件列表

group_message_event

功能描述: 当机器人收到群聊消息时触发,用于处理群内的消息交互。

语法:

bus.on("group_message_event", function(data) {
// 处理群消息逻辑
// 可以返回 true 来阻止后续处理
});

参数:

  • data (GroupMessageEvent): 群消息事件数据对象

返回值:

  • voidundefined: 允许后续处理
  • true: 阻止后续事件处理

使用示例:

bus.on("group_message_event", function(data) {
logger.info("收到群消息: 群 {0}, 用户 {1}: {2}",
data.groupId, data.userId, data.message);

// 简单的命令处理
if (data.message === "!ping") {
// 发送回复消息
data.reply("pong!");
return true; // 阻止后续处理
}

// 关键词回复
if (data.message.includes("服务器状态")) {
const serverCount = sessions.GetSessions().length;
data.reply(`当前有 ${serverCount} 个服务器在线`);
}
});

相关 API:


direct_message_event

功能描述: 当机器人收到私聊消息时触发,用于处理一对一的消息交互。

语法:

bus.on("direct_message_event", function(data) {
// 处理私聊消息逻辑
// 可以返回 true 来阻止后续处理
});

参数:

  • data (DirectMessageEvent): 私聊消息事件数据对象

返回值:

  • voidundefined: 允许后续处理
  • true: 阻止后续事件处理

使用示例:

bus.on("direct_message_event", function(data) {
logger.info("收到私聊消息: 用户 {0}: {1}", data.userId, data.message);

// 私聊命令处理
if (data.message === "!help") {
data.reply("可用命令:\n!bind - 绑定账号\n!status - 查看状态\n!servers - 服务器列表");
return true;
}

// 账号绑定流程
if (data.message.startsWith("!bind ")) {
const playerName = data.message.substring(6).trim();
if (playerName) {
// 这里实现绑定逻辑
data.reply(`正在为您绑定玩家: ${playerName}`);
// TODO: 实际的绑定逻辑
} else {
data.reply("请提供玩家名称,格式: !bind 玩家名");
}
return true;
}
});

group_join_event

功能描述: 当有新成员加入群聊时触发,用于处理新成员欢迎等逻辑。

语法:

bus.on("group_join_event", function(data) {
// 处理群成员加入逻辑
// 可以返回 true 来阻止后续处理
});

参数:

  • data (GroupJoinEvent): 群成员加入事件数据对象

返回值:

  • voidundefined: 允许后续处理
  • true: 阻止后续事件处理

使用示例:

bus.on("group_join_event", function(data) {
logger.info("新成员加入群 {0}: 用户 {1}", data.groupId, data.userId);

// 发送欢迎消息
const welcomeMessage = `欢迎新成员 @${data.userId} 加入群聊!\n` +
`请阅读群公告,输入 !help 查看可用命令。`;

data.sendGroupMessage(welcomeMessage);

// 记录加入时间
db.Set(`user:${data.userId}:joinTime:${data.groupId}`, new Date().toISOString());
});

group_leave_event

功能描述: 当群成员退出群聊时触发,用于处理成员离开的相关逻辑。

语法:

bus.on("group_leave_event", function(data) {
// 处理群成员退出逻辑
// 可以返回 true 来阻止后续处理
});

参数:

  • data (GroupLeaveEvent): 群成员退出事件数据对象

返回值:

  • voidundefined: 允许后续处理
  • true: 阻止后续事件处理

使用示例:

bus.on("group_leave_event", function(data) {
logger.info("成员退出群 {0}: 用户 {1}", data.groupId, data.userId);

// 检查是否为绑定用户
const playerName = db.GetString(`user:${data.userId}:playerName`);
if (playerName) {
logger.info("绑定玩家 {0} 的用户退出了群聊", playerName);

// 可以选择是否自动解绑
// db.Delete(`user:${data.userId}:playerName`);
// db.Delete(`player:${playerName}:userId`);
}

// 清理相关数据
db.Delete(`user:${data.userId}:joinTime:${data.groupId}`);
});

group_request_event

功能描述: 当有用户申请加入群聊时触发,用于处理入群申请的审核逻辑。

语法:

bus.on("group_request_event", function(data) {
// 处理入群申请逻辑
// 可以返回 true 来阻止后续处理
});

参数:

  • data (GroupRequestEvent): 入群申请事件数据对象

返回值:

  • voidundefined: 允许后续处理
  • true: 阻止后续事件处理

使用示例:

bus.on("group_request_event", function(data) {
logger.info("收到入群申请: 群 {0}, 用户 {1}, 消息: {2}",
data.groupId, data.userId, data.comment);

// 自动审核逻辑
const comment = data.comment || "";

// 检查申请消息是否包含关键词
if (comment.includes("minecraft") || comment.includes("MC") || comment.includes("我的世界")) {
// 自动同意
data.approve("欢迎加入Minecraft群聊!");
logger.info("自动同意用户 {0} 的入群申请", data.userId);
} else {
// 需要管理员审核
logger.info("用户 {0} 的入群申请需要人工审核", data.userId);

// 通知管理员
data.sendGroupMessage(`收到新的入群申请,请管理员审核\n用户: ${data.userId}\n申请消息: ${comment}`);
}
});

raw_message_event

功能描述: 当适配器收到任何形式的原始数据包时触发,用于实现高级功能和调试。

语法:

bus.on("raw_message_event", function(data) {
// 处理原始消息逻辑
// 可以返回 true 来阻止后续处理
});

参数:

  • data (RawMessageEvent): 原始消息事件数据对象

返回值:

  • voidundefined: 允许后续处理
  • true: 阻止后续事件处理

使用示例:

bus.on("raw_message_event", function(data) {
// 仅在调试模式下记录原始数据
if (DEBUG_MODE) {
logger.info("收到原始消息: 适配器 {0}, 类型 {1}",
data.adapterId, data.messageType);
logger.info("原始数据: {0}", JSON.stringify(data.rawData).substring(0, 200));
}

// 处理特殊的原始消息类型
if (data.messageType === "notice" && data.rawData.notice_type === "group_card") {
logger.info("群名片变更事件: 群 {0}, 用户 {1}",
data.rawData.group_id, data.rawData.user_id);
}

// 统计消息类型
const messageType = data.messageType || "unknown";
const count = db.GetNumber(`stats:message_type:${messageType}`, 0) + 1;
db.Set(`stats:message_type:${messageType}`, count);
});

实用示例

1. 智能客服系统

// 智能客服系统
let userSessions = {};

bus.on("group_message_event", function(data) {
const userId = data.userId;
const message = data.message;

// 常见问题自动回复
const faq = {
"如何绑定": "请私聊机器人发送: !bind 你的游戏名",
"服务器地址": "服务器地址: play.example.com",
"如何加白名单": "请先绑定账号,然后联系管理员",
"忘记密码": "请联系管理员重置密码"
};

for (const [keyword, answer] of Object.entries(faq)) {
if (message.includes(keyword)) {
data.reply(answer);
return true;
}
}
});

bus.on("direct_message_event", function(data) {
const userId = data.userId;
const message = data.message;

// 维护用户会话状态
if (!userSessions[userId]) {
userSessions[userId] = { step: "start" };
}

const session = userSessions[userId];

if (session.step === "start" && message === "!bind") {
session.step = "waiting_player_name";
data.reply("请输入您的Minecraft游戏名:");
return true;
}

if (session.step === "waiting_player_name") {
const playerName = message.trim();
if (playerName.match(/^[a-zA-Z0-9_]{3,16}$/)) {
// 验证玩家名格式正确
session.playerName = playerName;
session.step = "confirming";
data.reply(`确认绑定玩家: ${playerName}?\n回复 "确认" 或 "取消"`);
} else {
data.reply("玩家名格式不正确,请重新输入:");
}
return true;
}

if (session.step === "confirming") {
if (message === "确认") {
// 执行绑定逻辑
db.Set(`user:${userId}:playerName`, session.playerName);
db.Set(`player:${session.playerName}:userId`, userId);

data.reply(`绑定成功!您的账号已与玩家 ${session.playerName} 绑定`);
delete userSessions[userId];
} else if (message === "取消") {
data.reply("绑定已取消");
delete userSessions[userId];
} else {
data.reply("请回复 "确认" 或 "取消"");
}
return true;
}
});

2. 群管理系统

// 群管理系统
let groupSettings = {};

bus.on("group_message_event", function(data) {
const groupId = data.groupId;
const userId = data.userId;
const message = data.message;

// 初始化群设置
if (!groupSettings[groupId]) {
groupSettings[groupId] = {
welcomeEnabled: true,
autoKickSpam: true,
allowedCommands: ["!help", "!bind", "!status"]
};
}

const settings = groupSettings[groupId];

// 反垃圾消息
if (settings.autoKickSpam) {
if (message.length > 500 || message.includes("广告") || message.includes("代练")) {
logger.warning("检测到垃圾消息,用户: {0}", userId);
data.kickUser(userId, "发送垃圾消息");
return true;
}
}

// 命令权限检查
if (message.startsWith("!")) {
const command = message.split(" ")[0];
if (!settings.allowedCommands.includes(command)) {
data.reply("该命令在此群中不可用");
return true;
}
}
});

bus.on("group_join_event", function(data) {
const groupId = data.groupId;
const settings = groupSettings[groupId];

if (settings && settings.welcomeEnabled) {
const welcomeMsg = `欢迎 @${data.userId} 加入群聊!\n` +
`请遵守群规,输入 !help 查看可用命令。`;

setTimeout(() => {
data.sendGroupMessage(welcomeMsg);
}, 1000); // 延迟1秒发送
}
});

3. 服务器状态播报

// 服务器状态播报系统
let statusBroadcastGroups = ["123456789", "987654321"]; // 播报群列表

// 定期播报服务器状态
setInterval(function() {
const servers = sessions.GetSessions();
let statusMessage = "📊 服务器状态播报\n\n";

if (servers.length === 0) {
statusMessage += "❌ 暂无服务器在线";
} else {
for (let i = 0; i < servers.length; i++) {
const session = servers[i];
const bridge = sessions.GetBridge(session);

statusMessage += `🟢 服务器 ${i + 1}: ${session.id}\n`;

// 获取玩家数量
bridge.GetPlayerListAsync().then(function(playerInfo) {
statusMessage += ` 👥 在线玩家: ${playerInfo.players.length}\n`;
}).catch(function() {
statusMessage += ` 👥 在线玩家: 获取失败\n`;
});
}
}

// 向所有播报群发送状态
statusBroadcastGroups.forEach(function(groupId) {
// 这里需要根据实际的机器人API发送群消息
// robot.sendGroupMessage(groupId, statusMessage);
});

}, 30 * 60 * 1000); // 每30分钟播报一次

// 监听服务器上下线事件
bus.on("bridge_server_online", function(server, ip) {
const message = `🟢 服务器上线通知\n服务器: ${server.Session}\nIP: ${ip}`;

statusBroadcastGroups.forEach(function(groupId) {
// robot.sendGroupMessage(groupId, message);
});
});

bus.on("bridge_server_offline", function(server, closeCode, reason, ip) {
const message = `🔴 服务器离线通知\n服务器: ${server.Session}\n原因: ${reason}`;

statusBroadcastGroups.forEach(function(groupId) {
// robot.sendGroupMessage(groupId, message);
});
});

4. 用户权限管理

// 用户权限管理系统
let userPermissions = {};

// 初始化管理员权限
function initializePermissions() {
const admins = ["123456789", "987654321"]; // 管理员QQ号
admins.forEach(function(userId) {
userPermissions[userId] = {
level: "admin",
permissions: ["kick", "ban", "manage_server", "view_logs"]
};
});
}

function hasPermission(userId, permission) {
const user = userPermissions[userId];
return user && user.permissions.includes(permission);
}

bus.on("group_message_event", function(data) {
const message = data.message;
const userId = data.userId;

// 管理员命令
if (message.startsWith("!admin ")) {
if (!hasPermission(userId, "manage_server")) {
data.reply("您没有管理员权限");
return true;
}

const command = message.substring(7);

if (command === "restart") {
data.reply("正在重启所有服务器...");
// 执行重启逻辑
const bridges = sessions.GetBridges();
for (let i = 0; i < bridges.length; i++) {
bridges[i].SendRunCommandAsync("Console", "restart", false);
}
}

if (command.startsWith("kick ")) {
const playerName = command.substring(5);
data.reply(`正在踢出玩家: ${playerName}`);
// 执行踢人逻辑
}

return true;
}

// 普通用户命令
if (message === "!status") {
const serverCount = sessions.GetSessions().length;
data.reply(`当前有 ${serverCount} 个服务器在线`);
return true;
}
});

// 初始化权限
initializePermissions();

相关 API 参考

注意事项

  1. 适配器兼容性: 不同的机器人适配器可能有细微差异,测试时注意兼容性
  2. 消息格式: 注意消息格式的处理,支持文本、图片、@等多种类型
  3. 权限管理: 实现命令权限检查,防止普通用户执行管理员命令
  4. 错误处理: 在事件处理函数中使用 try-catch 避免异常影响其他监听器
  5. 性能考虑: 群消息是高频事件,避免在其中执行耗时操作
  6. 数据持久化: 重要的用户数据和设置应该持久化存储