修复MaiBot适配器群聊误判为私聊并补充路由诊断日志
变更项:\n1. 新增统一会话路由解析函数 _resolve_chat_route,按 plugin_roomid -> wx_roomid -> wx_to_user -> 原始报文 From/ToUserName 逐级兜底识别群聊。\n2. can_process 与转发构包统一使用同一套路由判定,避免采集判定和发送判定不一致。\n3. 在 additional_config 中新增 abot_route_type 与 abot_route_source,便于服务端链路排查。\n4. 补充详细路由日志,记录 route_type、route_source、plugin_roomid、wx_roomid、wx_to_user、sender、message_id。\n5. 入队日志增加 route_type/route_source 字段,便于快速筛查是否持续发生私聊误判。
This commit is contained in:
@@ -166,8 +166,8 @@ class MaiBotAdapterPlugin(MessagePluginInterface):
|
||||
if isinstance(full_msg, WxMessage) and full_msg.from_self():
|
||||
return False
|
||||
|
||||
roomid = str(message.get("roomid", "") or "").strip()
|
||||
if roomid:
|
||||
chat_route = self._resolve_chat_route(message)
|
||||
if chat_route["is_group"]:
|
||||
return self._collect_group_messages
|
||||
return self._collect_private_messages
|
||||
|
||||
@@ -193,7 +193,8 @@ class MaiBotAdapterPlugin(MessagePluginInterface):
|
||||
try:
|
||||
outbound_queue.put_nowait(payload)
|
||||
self.LOG.info(
|
||||
f"[{self.name}] 消息已入队: roomid={payload['roomid']}, sender={payload['sender']}, "
|
||||
f"[{self.name}] 消息已入队: route_type={payload['route_type']}, roomid={payload['roomid']}, "
|
||||
f"route_source={payload['route_source']}, sender={payload['sender']}, "
|
||||
f"msg_type={payload['message_type']}, queue_size={outbound_queue.qsize()}, "
|
||||
f"content_preview={normalized_content[:120]}"
|
||||
)
|
||||
@@ -491,7 +492,11 @@ class MaiBotAdapterPlugin(MessagePluginInterface):
|
||||
def _build_outbound_payload(self, message: Dict[str, Any], normalized_content: str) -> Dict[str, Any]:
|
||||
"""把微信消息包装成 MaiBot 官方 API Server 的 APIMessageBase 结构。"""
|
||||
full_msg = message.get("full_wx_msg")
|
||||
roomid = str(message.get("roomid", "") or "").strip()
|
||||
# 会话路由统一在这里解析,避免“can_process 一套、转发又一套”导致判定漂移。
|
||||
chat_route = self._resolve_chat_route(message)
|
||||
roomid = chat_route["roomid"]
|
||||
route_type = chat_route["route_type"]
|
||||
route_source = chat_route["route_source"]
|
||||
sender = str(message.get("sender", "") or "").strip()
|
||||
msg_type = self._resolve_message_type(message)
|
||||
timestamp = self._resolve_message_timestamp(message, full_msg)
|
||||
@@ -500,6 +505,15 @@ class MaiBotAdapterPlugin(MessagePluginInterface):
|
||||
sender_name = self._resolve_sender_name(message, sender)
|
||||
group_name = self._resolve_group_name(message, roomid)
|
||||
|
||||
# 路由诊断日志:这里把关键字段一次性打全,便于定位“群消息为何被识别成私聊”。
|
||||
self.LOG.info(
|
||||
f"[{self.name}] 路由判定: route_type={route_type}, route_source={route_source}, "
|
||||
f"plugin_roomid={str(message.get('roomid', '') or '').strip()}, "
|
||||
f"wx_roomid={str(getattr(full_msg, 'roomid', '') or '').strip() if isinstance(full_msg, WxMessage) else ''}, "
|
||||
f"wx_to_user={str(getattr(full_msg, 'to_user', '') or '').strip() if isinstance(full_msg, WxMessage) else ''}, "
|
||||
f"sender={sender}, message_id={message_id}"
|
||||
)
|
||||
|
||||
sender_info: Dict[str, Any] = {
|
||||
"user_info": {
|
||||
"platform": self._platform_name,
|
||||
@@ -545,6 +559,9 @@ class MaiBotAdapterPlugin(MessagePluginInterface):
|
||||
"is_at": bool(message.get("is_at", False)),
|
||||
"wx_message_type": msg_type,
|
||||
"collect_only": True,
|
||||
# 额外把本地路由判定结果透传给 MaiBot,便于服务端/日志排查“为何被识别成私聊”。
|
||||
"abot_route_type": route_type,
|
||||
"abot_route_source": route_source,
|
||||
},
|
||||
"sender_info": sender_info,
|
||||
"receiver_info": receiver_info,
|
||||
@@ -560,6 +577,8 @@ class MaiBotAdapterPlugin(MessagePluginInterface):
|
||||
}
|
||||
|
||||
return {
|
||||
"route_type": route_type,
|
||||
"route_source": route_source,
|
||||
"roomid": roomid,
|
||||
"sender": sender,
|
||||
"message_type": msg_type,
|
||||
@@ -568,6 +587,51 @@ class MaiBotAdapterPlugin(MessagePluginInterface):
|
||||
"api_message": api_message,
|
||||
}
|
||||
|
||||
def _resolve_chat_route(self, message: Dict[str, Any]) -> Dict[str, str]:
|
||||
"""解析消息的群聊/私聊路由,兼容上游字段缺失场景。"""
|
||||
full_msg = message.get("full_wx_msg")
|
||||
|
||||
# 先看插件消息里已经带好的 roomid,这是最直接、最便宜的一跳。
|
||||
plugin_roomid = str(message.get("roomid", "") or "").strip()
|
||||
if plugin_roomid.endswith("@chatroom"):
|
||||
return {"is_group": True, "route_type": "group", "roomid": plugin_roomid, "route_source": "plugin_roomid"}
|
||||
|
||||
# 再看 WxMessage 里计算过的 roomid。
|
||||
wx_roomid = ""
|
||||
wx_to_user = ""
|
||||
wx_from_group = False
|
||||
if isinstance(full_msg, WxMessage):
|
||||
wx_roomid = str(getattr(full_msg, "roomid", "") or "").strip()
|
||||
wx_to_user = str(getattr(full_msg, "to_user", "") or "").strip()
|
||||
try:
|
||||
wx_from_group = bool(full_msg.from_group())
|
||||
except Exception:
|
||||
wx_from_group = False
|
||||
|
||||
if wx_roomid.endswith("@chatroom"):
|
||||
return {"is_group": True, "route_type": "group", "roomid": wx_roomid, "route_source": "wx_roomid"}
|
||||
|
||||
# 某些边界消息里,roomid 可能没落下来,但 to_user 仍是 chatroom。
|
||||
if wx_to_user.endswith("@chatroom"):
|
||||
return {"is_group": True, "route_type": "group", "roomid": wx_to_user, "route_source": "wx_to_user"}
|
||||
|
||||
# 最后兜底原始报文,避免上游字段偶发缺失时把群消息误判成私聊。
|
||||
raw_data = getattr(full_msg, "raw_data", {}) if isinstance(full_msg, WxMessage) else {}
|
||||
raw_from = ""
|
||||
raw_to = ""
|
||||
if isinstance(raw_data, dict):
|
||||
raw_from = str(((raw_data.get("FromUserName") or {}).get("string")) or "").strip()
|
||||
raw_to = str(((raw_data.get("ToUserName") or {}).get("string")) or "").strip()
|
||||
|
||||
if raw_from.endswith("@chatroom"):
|
||||
return {"is_group": True, "route_type": "group", "roomid": raw_from, "route_source": "raw_from_user"}
|
||||
if raw_to.endswith("@chatroom"):
|
||||
return {"is_group": True, "route_type": "group", "roomid": raw_to, "route_source": "raw_to_user"}
|
||||
|
||||
# 到这里仍不是群聊,就按私聊处理,但保留详细来源,方便日志反查。
|
||||
private_source = "wx_from_group_flag" if wx_from_group else "private_default"
|
||||
return {"is_group": False, "route_type": "private", "roomid": "", "route_source": private_source}
|
||||
|
||||
def _resolve_reply_route(self, message_info: Dict[str, Any]) -> Optional[Dict[str, str]]:
|
||||
"""从 MaiBot 返回的 message_info 中解析微信路由。"""
|
||||
receiver_info = message_info.get("receiver_info") or {}
|
||||
@@ -794,4 +858,3 @@ class MaiBotAdapterPlugin(MessagePluginInterface):
|
||||
self.LOG.warning(f"[{self.name}] 关闭 ClientSession 失败: {exc}")
|
||||
finally:
|
||||
self._client_session = None
|
||||
|
||||
|
||||
Reference in New Issue
Block a user