feat:识别群昵称

This commit is contained in:
2025-12-23 16:46:41 +08:00
parent cc250e1f1e
commit 2c564d2870
6 changed files with 320 additions and 15 deletions

View File

@@ -195,6 +195,10 @@ class AutoReply(PluginBase):
if not content:
return True
# 跳过指令类消息(避免和各插件命令冲突、也避免“命令触发后又被自动回复补一句”)
if content.startswith("/"):
return True
# 跳过机器人自己的消息
if self._is_bot_message(message):
return True
@@ -297,6 +301,13 @@ class AutoReply(PluginBase):
self._update_state(chat_id, replied=False)
return
# 如果在判断期间机器人已经发过言(例如 AIChat/@回复或其他插件回复),则跳过本次主动回复
# 避免同一条消息触发“回复两次”的观感。
if await self._bot_replied_since(pending.from_wxid, pending.trigger_time):
logger.info(f"[AutoReply] 检测到机器人已回复,跳过自动回复 | 群:{pending.from_wxid[:15]}...")
self._update_state(chat_id, replied=False)
return
# 触发回复
logger.info(f"[AutoReply] 触发回复 | 群:{pending.from_wxid[:15]}... | 评分:{judge_result.overall_score:.2f} | 耗时:{elapsed_time:.1f}s | {judge_result.reasoning[:30]}")
@@ -320,6 +331,55 @@ class AutoReply(PluginBase):
if chat_id in self.pending_tasks:
del self.pending_tasks[chat_id]
def _parse_history_timestamp(self, ts) -> Optional[float]:
"""将历史记录中的 timestamp 转成 epoch 秒。"""
if ts is None:
return None
if isinstance(ts, (int, float)):
return float(ts)
if isinstance(ts, str):
s = ts.strip()
if not s:
return None
try:
return float(s)
except ValueError:
pass
try:
return datetime.fromisoformat(s).timestamp()
except Exception:
return None
return None
async def _bot_replied_since(self, group_id: str, since_ts: float) -> bool:
"""检查 group_id 在 since_ts 之后是否出现过机器人回复。"""
try:
history = await self._get_history(group_id)
if not history:
return False
since_ts = float(since_ts or 0)
if since_ts <= 0:
return False
# 只看最近一小段即可:如果机器人真的在这段时间回复了,必然会出现在末尾附近
for record in reversed(history[-120:]):
role = record.get("role")
nickname = record.get("nickname")
if role != "assistant" and not (self.bot_nickname and nickname == self.bot_nickname):
continue
ts = record.get("timestamp") or record.get("time") or record.get("CreateTime")
epoch = self._parse_history_timestamp(ts)
if epoch is None:
return False
return epoch >= since_ts
return False
except Exception as e:
logger.debug(f"[AutoReply] bot reply 检查失败: {e}")
return False
async def _trigger_ai_reply(self, bot, from_wxid: str):
"""触发 AIChat 生成回复(基于最新历史上下文)"""
try: