ForcePilot/backend/package/yuxi/channels/adapters/imessage/directory.py
Kris 068cf70fe9 feat(imessage): 实现完整的 iMessage 适配器基础模块
新增 iMessage 通道适配器完整实现,包含:
1. 核心适配器与工具工厂导出
2. 运行时存储、反射防护、会话路由等基础组件
3. 消息信封、线程管理、回复上下文格式化
4. Tapback 表情反应处理、自定义异常体系
5. 审批按钮、联系人解析、速率限制功能
6. 文本净化、目标解析、缓存管理模块
7. 配置 schema、多账户支持、安装向导等配置模块
8. 审计日志、媒体AI处理等扩展功能
2026-05-12 00:44:44 +08:00

66 lines
2.5 KiB
Python

from __future__ import annotations
from typing import Any
from yuxi.channels.adapters.imessage.bridge_client import BlueBubblesClient
from yuxi.utils.logging_config import logger
async def search_contacts(bridge: BlueBubblesClient, query: str, limit: int = 20) -> list[dict[str, Any]]:
"""搜索联系人。"""
try:
contacts = await bridge.query_contacts([query])
return contacts[:limit]
except Exception as e:
logger.warning(f"[iMessage/Directory] Contact search failed: {e}")
return []
async def list_recent_chats(bridge: BlueBubblesClient, limit: int = 30) -> list[dict[str, Any]]:
"""获取最近聊天列表。"""
try:
chats = await bridge.get_chats()
chats.sort(key=lambda c: c.get("lastMessageDate", 0), reverse=True)
return chats[:limit]
except Exception as e:
logger.warning(f"[iMessage/Directory] Failed to list recent chats: {e}")
return []
async def search_groups(bridge: BlueBubblesClient, name_query: str, limit: int = 20) -> list[dict[str, Any]]:
"""搜索群组。"""
try:
chats = await bridge.get_chats()
groups = [c for c in chats if ";-;" in c.get("guid", "") or "@chat" in c.get("guid", "")]
if name_query:
name_lower = name_query.lower()
groups = [
g
for g in groups
if name_lower in g.get("displayName", "").lower() or name_lower in g.get("guid", "").lower()
]
groups.sort(key=lambda c: c.get("lastMessageDate", 0), reverse=True)
return groups[:limit]
except Exception as e:
logger.warning(f"[iMessage/Directory] Group search failed: {e}")
return []
async def get_chat_info(bridge: BlueBubblesClient, chat_guid: str) -> dict[str, Any]:
"""获取聊天详细信息。"""
try:
messages = await bridge.get_chat_messages(chat_guid, limit=1)
chats = await bridge.get_chats()
for chat in chats:
if chat.get("guid") == chat_guid:
return {
"guid": chat_guid,
"display_name": chat.get("displayName", ""),
"participants": chat.get("participants", []),
"last_message": messages[0] if messages else None,
}
return {"guid": chat_guid, "display_name": "", "participants": []}
except Exception as e:
logger.warning(f"[iMessage/Directory] Failed to get chat info for {chat_guid}: {e}")
return {"guid": chat_guid, "display_name": ""}