feat: 优化 Misskey 适配器的通知和聊天消息处理,改进 @用户提及逻辑 (#3075)
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import asyncio
|
||||
import random
|
||||
import json
|
||||
from typing import Dict, Any, Optional, Awaitable, List
|
||||
|
||||
from astrbot.api import logger
|
||||
@@ -270,10 +269,10 @@ class MisskeyPlatformAdapter(Platform):
|
||||
|
||||
async def _handle_notification(self, data: Dict[str, Any]):
|
||||
try:
|
||||
logger.debug(
|
||||
f"[Misskey] 收到通知事件:\n{json.dumps(data, indent=2, ensure_ascii=False)}"
|
||||
)
|
||||
notification_type = data.get("type")
|
||||
logger.debug(
|
||||
f"[Misskey] 收到通知事件: type={notification_type}, user_id={data.get('userId', 'unknown')}"
|
||||
)
|
||||
if notification_type in ["mention", "reply", "quote"]:
|
||||
note = data.get("note")
|
||||
if note and self._is_bot_mentioned(note):
|
||||
@@ -294,17 +293,16 @@ class MisskeyPlatformAdapter(Platform):
|
||||
|
||||
async def _handle_chat_message(self, data: Dict[str, Any]):
|
||||
try:
|
||||
logger.debug(
|
||||
f"[Misskey] 收到聊天事件数据:\n{json.dumps(data, indent=2, ensure_ascii=False)}"
|
||||
)
|
||||
|
||||
sender_id = str(
|
||||
data.get("fromUserId", "") or data.get("fromUser", {}).get("id", "")
|
||||
)
|
||||
room_id = data.get("toRoomId")
|
||||
logger.debug(
|
||||
f"[Misskey] 收到聊天事件: sender_id={sender_id}, room_id={room_id}, is_self={sender_id == self.client_self_id}"
|
||||
)
|
||||
if sender_id == self.client_self_id:
|
||||
return
|
||||
|
||||
room_id = data.get("toRoomId")
|
||||
if room_id:
|
||||
raw_text = data.get("text", "")
|
||||
logger.debug(
|
||||
@@ -329,8 +327,9 @@ class MisskeyPlatformAdapter(Platform):
|
||||
logger.error(f"[Misskey] 处理聊天消息失败: {e}")
|
||||
|
||||
async def _debug_handler(self, data: Dict[str, Any]):
|
||||
event_type = data.get("type", "unknown")
|
||||
logger.debug(
|
||||
f"[Misskey] 收到未处理事件:\n{json.dumps(data, indent=2, ensure_ascii=False)}"
|
||||
f"[Misskey] 收到未处理事件: type={event_type}, channel={data.get('channel', 'unknown')}"
|
||||
)
|
||||
|
||||
def _is_bot_mentioned(self, note: Dict[str, Any]) -> bool:
|
||||
@@ -365,7 +364,18 @@ class MisskeyPlatformAdapter(Platform):
|
||||
text, has_at_user = serialize_message_chain(message_chain.chain)
|
||||
|
||||
if not has_at_user and session_id:
|
||||
user_info = self._user_cache.get(session_id)
|
||||
# 从session_id中提取用户ID用于缓存查询
|
||||
# session_id格式为: "chat%<user_id>" 或 "room%<room_id>" 或 "note%<user_id>"
|
||||
user_id_for_cache = None
|
||||
if "%" in session_id:
|
||||
parts = session_id.split("%")
|
||||
if len(parts) >= 2:
|
||||
user_id_for_cache = parts[1]
|
||||
|
||||
user_info = None
|
||||
if user_id_for_cache:
|
||||
user_info = self._user_cache.get(user_id_for_cache)
|
||||
|
||||
text = add_at_mention_if_needed(text, user_info, has_at_user)
|
||||
|
||||
# 检查是否有文件组件
|
||||
@@ -560,6 +570,10 @@ class MisskeyPlatformAdapter(Platform):
|
||||
user_id_for_cache = (
|
||||
session_id.split("%")[1] if "%" in session_id else session_id
|
||||
)
|
||||
|
||||
# 获取用户缓存信息(包含reply_to_note_id)
|
||||
user_info_for_reply = self._user_cache.get(user_id_for_cache, {})
|
||||
|
||||
visibility, visible_user_ids = resolve_message_visibility(
|
||||
user_id=user_id_for_cache,
|
||||
user_cache=self._user_cache,
|
||||
@@ -575,12 +589,16 @@ class MisskeyPlatformAdapter(Platform):
|
||||
appended = "\n" + "\n".join(fallback_urls)
|
||||
text = (text or "") + appended
|
||||
|
||||
# 从缓存中获取原消息ID作为reply_id
|
||||
reply_id = user_info_for_reply.get("reply_to_note_id")
|
||||
|
||||
await self.api.create_note(
|
||||
text=text,
|
||||
visibility=visibility,
|
||||
visible_user_ids=visible_user_ids,
|
||||
file_ids=file_ids or None,
|
||||
local_only=self.local_only,
|
||||
reply_id=reply_id, # 添加reply_id参数
|
||||
cw=fields["cw"],
|
||||
poll=fields["poll"],
|
||||
renote_id=fields["renote_id"],
|
||||
|
||||
@@ -222,10 +222,6 @@ class StreamingClient:
|
||||
channel_summary = _build_channel_summary(message_type, body)
|
||||
logger.info(channel_summary)
|
||||
|
||||
logger.debug(
|
||||
f"[Misskey WebSocket] 收到完整消息: {json.dumps(data, indent=2, ensure_ascii=False)}"
|
||||
)
|
||||
|
||||
if message_type == "channel":
|
||||
channel_id = body.get("id")
|
||||
event_type = body.get("type")
|
||||
|
||||
@@ -84,7 +84,12 @@ def serialize_message_chain(chain: List[Any]) -> Tuple[str, bool]:
|
||||
return "[图片]"
|
||||
elif isinstance(component, Comp.At):
|
||||
has_at = True
|
||||
return f"@{component.qq}"
|
||||
# 优先使用name字段(用户名),如果没有则使用qq字段
|
||||
# 这样可以避免在Misskey中生成 @<user_id> 这样的无效提及
|
||||
if hasattr(component, "name") and component.name:
|
||||
return f"@{component.name}"
|
||||
else:
|
||||
return f"@{component.qq}"
|
||||
elif hasattr(component, "text"):
|
||||
text = getattr(component, "text", "")
|
||||
if "@" in text:
|
||||
@@ -233,21 +238,22 @@ def extract_room_id_from_session_id(session_id: str) -> str:
|
||||
def add_at_mention_if_needed(
|
||||
text: str, user_info: Optional[Dict[str, Any]], has_at: bool = False
|
||||
) -> str:
|
||||
"""如果需要且没有@用户,则添加@用户"""
|
||||
"""如果需要且没有@用户,则添加@用户
|
||||
|
||||
注意:仅在有有效的username时才添加@提及,避免使用用户ID
|
||||
"""
|
||||
if has_at or not user_info:
|
||||
return text
|
||||
|
||||
username = user_info.get("username")
|
||||
nickname = user_info.get("nickname")
|
||||
# 如果没有username,则不添加@提及,返回原文本
|
||||
# 这样可以避免生成 @<user_id> 这样的无效提及
|
||||
if not username:
|
||||
return text
|
||||
|
||||
if username:
|
||||
mention = f"@{username}"
|
||||
if not text.startswith(mention):
|
||||
text = f"{mention}\n{text}".strip()
|
||||
elif nickname:
|
||||
mention = f"@{nickname}"
|
||||
if not text.startswith(mention):
|
||||
text = f"{mention}\n{text}".strip()
|
||||
mention = f"@{username}"
|
||||
if not text.startswith(mention):
|
||||
text = f"{mention}\n{text}".strip()
|
||||
|
||||
return text
|
||||
|
||||
@@ -403,6 +409,8 @@ def cache_user_info(
|
||||
"nickname": sender_info["nickname"],
|
||||
"visibility": raw_data.get("visibility", "public"),
|
||||
"visible_user_ids": raw_data.get("visibleUserIds", []),
|
||||
# 保存原消息ID,用于回复时作为reply_id
|
||||
"reply_to_note_id": raw_data.get("id"),
|
||||
}
|
||||
|
||||
user_cache[sender_info["sender_id"]] = user_cache_data
|
||||
|
||||
Reference in New Issue
Block a user