1. 统一调整多个文件的导入排序,将TYPE_CHECKING相关导入放在正确位置 2. 修复rate_limiter中当限制数<=0时直接返回false的逻辑 3. 为message_cache新增更新消息内容的方法 4. 重构extract_graph_content支持日记类型内容提取 5. 调整@提及匹配的正则表达式,避免误匹配 6. 完善invite_manager,添加客户端和凭据支持并实现自动接受群邀请逻辑 7. 调整adapter.py中的导入顺序和初始化逻辑 8. 修复monitor中的编辑事件处理,改为异步处理并实现消息更新缓存 9. 调整datetime导入顺序,统一使用UTC在前的格式
76 lines
2.3 KiB
Python
76 lines
2.3 KiB
Python
from __future__ import annotations
|
|
|
|
import time
|
|
from collections import defaultdict
|
|
|
|
from yuxi.channels.models import ChannelMessage
|
|
from yuxi.utils.logging_config import logger
|
|
|
|
|
|
def resolve_thread_key(msg: ChannelMessage, default_agent_id: str = "ChatbotAgent") -> str:
|
|
chat_type = msg.metadata.get("chat_type", "group")
|
|
chat_id = msg.identity.channel_chat_id
|
|
|
|
if chat_type == "direct":
|
|
return f"agent:{default_agent_id}:urbit:direct:{chat_id}"
|
|
|
|
group_name = msg.metadata.get("group_name", chat_id)
|
|
ch_type = msg.metadata.get("urbit_resource_type", "chat")
|
|
return f"agent:{default_agent_id}:urbit:group:{group_name}:{ch_type}"
|
|
|
|
|
|
def resolve_session_route(msg: ChannelMessage, default_agent_id: str = "ChatbotAgent") -> str:
|
|
return resolve_thread_key(msg, default_agent_id)
|
|
|
|
|
|
_unsafe_sessions: defaultdict[str, set[str]] = defaultdict(set)
|
|
_session_last_access: dict[str, float] = {}
|
|
_SESSION_TTL_S = 3600
|
|
|
|
|
|
def detect_unsafe_session(msg: ChannelMessage) -> list[str]:
|
|
chat_type = msg.metadata.get("chat_type", "group")
|
|
if chat_type != "direct":
|
|
return []
|
|
|
|
chat_id = msg.identity.channel_chat_id
|
|
participant_key = f"dm:{chat_id}"
|
|
sender_ship = msg.metadata.get("urbit_ship", "")
|
|
|
|
if not sender_ship:
|
|
return []
|
|
|
|
_unsafe_sessions[participant_key].add(sender_ship)
|
|
_session_last_access[participant_key] = time.monotonic()
|
|
participants = _unsafe_sessions[participant_key]
|
|
|
|
if len(participants) > 2:
|
|
logger.warning(
|
|
f"[Urbit] Unsafe DM session detected: "
|
|
f"{participant_key} has {len(participants)} "
|
|
f"participants: {participants}"
|
|
)
|
|
return list(participants)
|
|
|
|
return []
|
|
|
|
|
|
def get_unsafe_sessions() -> dict[str, set[str]]:
|
|
return dict(_unsafe_sessions)
|
|
|
|
|
|
def clear_unsafe_sessions() -> None:
|
|
_unsafe_sessions.clear()
|
|
_session_last_access.clear()
|
|
|
|
|
|
def cleanup_expired_sessions() -> int:
|
|
now = time.monotonic()
|
|
expired = [key for key, ts in _session_last_access.items() if now - ts > _SESSION_TTL_S]
|
|
for key in expired:
|
|
_unsafe_sessions.pop(key, None)
|
|
_session_last_access.pop(key, None)
|
|
if expired:
|
|
logger.debug(f"[Urbit] Cleaned up {len(expired)} expired unsafe session records")
|
|
return len(expired)
|