feat(napcat): 添加事件处理过滤机制,支持黑白名单功能
This commit is contained in:
@@ -88,6 +88,93 @@ class NapcatAdapter(BaseAdapter):
|
|||||||
# 注册 utils 内部使用的适配器实例,便于工具方法自动获取 WS
|
# 注册 utils 内部使用的适配器实例,便于工具方法自动获取 WS
|
||||||
handler_utils.register_adapter(self)
|
handler_utils.register_adapter(self)
|
||||||
|
|
||||||
|
def _should_process_event(self, raw: Dict[str, Any]) -> bool:
|
||||||
|
"""
|
||||||
|
检查事件是否应该被处理(黑白名单过滤)
|
||||||
|
|
||||||
|
此方法在 from_platform_message 顶层调用,对所有类型的事件(消息、通知、元事件)进行过滤。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
raw: OneBot 原始事件数据
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True表示应该处理,False表示应该过滤
|
||||||
|
"""
|
||||||
|
if not self.plugin:
|
||||||
|
return True
|
||||||
|
|
||||||
|
plugin_config = self.plugin.config
|
||||||
|
if not plugin_config:
|
||||||
|
return True # 如果没有配置,默认处理所有事件
|
||||||
|
|
||||||
|
features_config = plugin_config.get("features", {})
|
||||||
|
post_type = raw.get("post_type")
|
||||||
|
|
||||||
|
# 获取用户信息(根据事件类型从不同字段获取)
|
||||||
|
user_id: str = ""
|
||||||
|
if post_type == "message":
|
||||||
|
sender_info = raw.get("sender", {})
|
||||||
|
user_id = str(sender_info.get("user_id", ""))
|
||||||
|
elif post_type == "notice":
|
||||||
|
user_id = str(raw.get("user_id", ""))
|
||||||
|
else:
|
||||||
|
# 元事件或其他类型不需要过滤
|
||||||
|
return True
|
||||||
|
|
||||||
|
# 检查全局封禁用户列表
|
||||||
|
ban_user_ids = [str(item) for item in features_config.get("ban_user_id", [])]
|
||||||
|
if user_id and user_id in ban_user_ids:
|
||||||
|
logger.debug(f"用户 {user_id} 在全局封禁列表中,事件被过滤")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 检查是否屏蔽其他QQ机器人(仅对消息事件生效)
|
||||||
|
if post_type == "message" and features_config.get("ban_qq_bot", False):
|
||||||
|
sender_info = raw.get("sender", {})
|
||||||
|
role = sender_info.get("role", "")
|
||||||
|
if role == "admin" or "bot" in str(sender_info).lower():
|
||||||
|
logger.debug(f"检测到机器人消息 {user_id},事件被过滤")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 获取消息类型(消息事件使用 message_type,通知事件根据 group_id 判断)
|
||||||
|
message_type = raw.get("message_type")
|
||||||
|
group_id = raw.get("group_id")
|
||||||
|
|
||||||
|
# 如果是通知事件,根据是否有 group_id 判断是群通知还是私聊通知
|
||||||
|
if post_type == "notice":
|
||||||
|
message_type = "group" if group_id else "private"
|
||||||
|
|
||||||
|
# 群聊/群通知过滤
|
||||||
|
if message_type == "group" and group_id:
|
||||||
|
group_id_str = str(group_id)
|
||||||
|
group_list_type = features_config.get("group_list_type", "blacklist")
|
||||||
|
group_list = [str(item) for item in features_config.get("group_list", [])]
|
||||||
|
|
||||||
|
if group_list_type == "blacklist":
|
||||||
|
if group_id_str in group_list:
|
||||||
|
logger.debug(f"群聊 {group_id_str} 在黑名单中,事件被过滤")
|
||||||
|
return False
|
||||||
|
else: # whitelist
|
||||||
|
if group_id_str not in group_list:
|
||||||
|
logger.debug(f"群聊 {group_id_str} 不在白名单中,事件被过滤")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 私聊/私聊通知过滤
|
||||||
|
elif message_type == "private":
|
||||||
|
private_list_type = features_config.get("private_list_type", "blacklist")
|
||||||
|
private_list = [str(item) for item in features_config.get("private_list", [])]
|
||||||
|
|
||||||
|
if private_list_type == "blacklist":
|
||||||
|
if user_id in private_list:
|
||||||
|
logger.debug(f"私聊用户 {user_id} 在黑名单中,事件被过滤")
|
||||||
|
return False
|
||||||
|
else: # whitelist
|
||||||
|
if user_id not in private_list:
|
||||||
|
logger.debug(f"私聊用户 {user_id} 不在白名单中,事件被过滤")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 通过所有过滤条件
|
||||||
|
return True
|
||||||
|
|
||||||
async def on_adapter_loaded(self) -> None:
|
async def on_adapter_loaded(self) -> None:
|
||||||
"""适配器加载时的初始化"""
|
"""适配器加载时的初始化"""
|
||||||
logger.info("Napcat 适配器正在启动...")
|
logger.info("Napcat 适配器正在启动...")
|
||||||
@@ -161,6 +248,8 @@ class NapcatAdapter(BaseAdapter):
|
|||||||
- notice 事件 → 通知(戳一戳、表情回复等)
|
- notice 事件 → 通知(戳一戳、表情回复等)
|
||||||
- meta_event 事件 → 元事件(心跳、生命周期)
|
- meta_event 事件 → 元事件(心跳、生命周期)
|
||||||
- API 响应 → 存入响应池
|
- API 响应 → 存入响应池
|
||||||
|
|
||||||
|
注意:黑白名单等过滤机制在此方法最开始执行,确保所有类型的事件都能被过滤。
|
||||||
"""
|
"""
|
||||||
post_type = raw.get("post_type")
|
post_type = raw.get("post_type")
|
||||||
|
|
||||||
@@ -171,6 +260,11 @@ class NapcatAdapter(BaseAdapter):
|
|||||||
future = self._response_pool[echo]
|
future = self._response_pool[echo]
|
||||||
if not future.done():
|
if not future.done():
|
||||||
future.set_result(raw)
|
future.set_result(raw)
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 顶层过滤:黑白名单等过滤机制
|
||||||
|
if not self._should_process_event(raw):
|
||||||
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 消息事件
|
# 消息事件
|
||||||
|
|||||||
@@ -39,79 +39,6 @@ class MessageHandler:
|
|||||||
"""设置插件配置"""
|
"""设置插件配置"""
|
||||||
self.plugin_config = config
|
self.plugin_config = config
|
||||||
|
|
||||||
def _should_process_message(self, raw: Dict[str, Any]) -> bool:
|
|
||||||
"""
|
|
||||||
检查消息是否应该被处理(黑白名单过滤)
|
|
||||||
|
|
||||||
Args:
|
|
||||||
raw: OneBot 原始消息数据
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: True表示应该处理,False表示应该过滤
|
|
||||||
"""
|
|
||||||
if not self.plugin_config:
|
|
||||||
return True # 如果没有配置,默认处理所有消息
|
|
||||||
|
|
||||||
features_config = self.plugin_config.get("features", {})
|
|
||||||
|
|
||||||
# 获取消息基本信息
|
|
||||||
message_type = raw.get("message_type")
|
|
||||||
sender_info = raw.get("sender", {})
|
|
||||||
user_id = str(sender_info.get("user_id", ""))
|
|
||||||
|
|
||||||
# 检查全局封禁用户列表
|
|
||||||
ban_user_ids = [str(item) for item in features_config.get("ban_user_id", [])]
|
|
||||||
if user_id in ban_user_ids:
|
|
||||||
logger.debug(f"用户 {user_id} 在全局封禁列表中,消息被过滤")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# 检查是否屏蔽其他QQ机器人
|
|
||||||
if features_config.get("ban_qq_bot", False):
|
|
||||||
# 判断是否为机器人消息:通常通过sender中的role字段或其他标识
|
|
||||||
role = sender_info.get("role", "")
|
|
||||||
if role == "admin" or "bot" in str(sender_info).lower():
|
|
||||||
logger.debug(f"检测到机器人消息 {user_id},消息被过滤")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# 群聊消息处理
|
|
||||||
if message_type == "group":
|
|
||||||
group_id = str(raw.get("group_id", ""))
|
|
||||||
|
|
||||||
# 获取群聊配置
|
|
||||||
group_list_type = features_config.get("group_list_type", "blacklist")
|
|
||||||
group_list = [str(item) for item in features_config.get("group_list", [])]
|
|
||||||
|
|
||||||
if group_list_type == "blacklist":
|
|
||||||
# 黑名单模式:如果在黑名单中就过滤
|
|
||||||
if group_id in group_list:
|
|
||||||
logger.debug(f"群聊 {group_id} 在黑名单中,消息被过滤")
|
|
||||||
return False
|
|
||||||
else: # whitelist
|
|
||||||
# 白名单模式:如果不在白名单中就过滤
|
|
||||||
if group_id not in group_list:
|
|
||||||
logger.debug(f"群聊 {group_id} 不在白名单中,消息被过滤")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# 私聊消息处理
|
|
||||||
elif message_type == "private":
|
|
||||||
# 获取私聊配置
|
|
||||||
private_list_type = features_config.get("private_list_type", "blacklist")
|
|
||||||
private_list = [str(item) for item in features_config.get("private_list", [])]
|
|
||||||
|
|
||||||
if private_list_type == "blacklist":
|
|
||||||
# 黑名单模式:如果在黑名单中就过滤
|
|
||||||
if user_id in private_list:
|
|
||||||
logger.debug(f"私聊用户 {user_id} 在黑名单中,消息被过滤")
|
|
||||||
return False
|
|
||||||
else: # whitelist
|
|
||||||
# 白名单模式:如果不在白名单中就过滤
|
|
||||||
if user_id not in private_list:
|
|
||||||
logger.debug(f"私聊用户 {user_id} 不在白名单中,消息被过滤")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# 通过所有过滤条件
|
|
||||||
return True
|
|
||||||
|
|
||||||
async def handle_raw_message(self, raw: Dict[str, Any]):
|
async def handle_raw_message(self, raw: Dict[str, Any]):
|
||||||
"""
|
"""
|
||||||
处理原始消息并转换为 MessageEnvelope
|
处理原始消息并转换为 MessageEnvelope
|
||||||
@@ -120,18 +47,17 @@ class MessageHandler:
|
|||||||
raw: OneBot 原始消息数据
|
raw: OneBot 原始消息数据
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
MessageEnvelope (dict) or None (if message is filtered)
|
MessageEnvelope (dict) or None
|
||||||
|
|
||||||
|
Note:
|
||||||
|
黑白名单过滤已移动到 NapcatAdapter.from_platform_message 顶层执行,
|
||||||
|
确保所有类型的事件(消息、通知等)都能被统一过滤。
|
||||||
"""
|
"""
|
||||||
|
|
||||||
message_type = raw.get("message_type")
|
message_type = raw.get("message_type")
|
||||||
message_id = str(raw.get("message_id", ""))
|
message_id = str(raw.get("message_id", ""))
|
||||||
message_time = time.time()
|
message_time = time.time()
|
||||||
|
|
||||||
# 黑白名单过滤
|
|
||||||
if not self._should_process_message(raw):
|
|
||||||
logger.debug(f"消息被黑白名单过滤丢弃: message_id={message_id}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
msg_builder = MessageBuilder()
|
msg_builder = MessageBuilder()
|
||||||
|
|
||||||
# 构造用户信息
|
# 构造用户信息
|
||||||
|
|||||||
Reference in New Issue
Block a user