新增 iMessage 通道适配器完整实现,包含: 1. 核心适配器与工具工厂导出 2. 运行时存储、反射防护、会话路由等基础组件 3. 消息信封、线程管理、回复上下文格式化 4. Tapback 表情反应处理、自定义异常体系 5. 审批按钮、联系人解析、速率限制功能 6. 文本净化、目标解析、缓存管理模块 7. 配置 schema、多账户支持、安装向导等配置模块 8. 审计日志、媒体AI处理等扩展功能
86 lines
2.3 KiB
Python
86 lines
2.3 KiB
Python
from __future__ import annotations
|
|
|
|
from yuxi.channels.models import ChatType
|
|
|
|
TARGET_PREFIX_MAP: dict[str, str] = {
|
|
"chat_id:": "chat_id",
|
|
"chat_guid:": "chat_guid",
|
|
"chat_identifier:": "chat_identifier",
|
|
"handle:": "handle",
|
|
"phone:": "phone",
|
|
"email:": "email",
|
|
}
|
|
|
|
EXPLICIT_TARGET_RE_PREFIXES = (
|
|
"chat_id:",
|
|
"chat_guid:",
|
|
"chat_identifier:",
|
|
"iMessage;",
|
|
"iMessage",
|
|
"handle:",
|
|
"phone:",
|
|
"email:",
|
|
)
|
|
|
|
IMESSAGE_TARGET_PREFIXES = (
|
|
"chat_id:",
|
|
"chat_guid:",
|
|
"chat_identifier:",
|
|
"iMessage;",
|
|
"iMessage",
|
|
"handle:",
|
|
"phone:",
|
|
"email:",
|
|
"tel:",
|
|
"mailto:",
|
|
"+",
|
|
)
|
|
|
|
|
|
def parse_target(raw_target: str) -> dict[str, str]:
|
|
"""解析目标字符串,返回 {type, value}。
|
|
|
|
支持的类型:
|
|
- chat_id:<value> → chat_id
|
|
- chat_guid:<value> → chat_guid
|
|
- chat_identifier:<value> → chat_identifier (chat_id 或 chat_guid)
|
|
- handle:<value> → handle
|
|
- phone:<value> → phone (E.164)
|
|
- email:<value> → email
|
|
- 其他:自动推断为 handle
|
|
"""
|
|
if not raw_target:
|
|
return {"type": "unknown", "value": ""}
|
|
|
|
raw_lower = raw_target.lower()
|
|
for prefix, type_name in TARGET_PREFIX_MAP.items():
|
|
if raw_lower.startswith(prefix):
|
|
return {"type": type_name, "value": raw_target[len(prefix) :]}
|
|
|
|
if looks_like_explicit_target_id(raw_target):
|
|
if ";-;" in raw_target or "@chat" in raw_target:
|
|
return {"type": "chat_guid", "value": raw_target}
|
|
if raw_target.startswith("iMessage;"):
|
|
return {"type": "chat_id", "value": raw_target}
|
|
|
|
if "@" in raw_target and "." in raw_target.split("@")[-1]:
|
|
return {"type": "email", "value": raw_target}
|
|
|
|
return {"type": "handle", "value": raw_target}
|
|
|
|
|
|
def looks_like_explicit_target_id(target: str) -> bool:
|
|
return any(target.lower().startswith(p.lower()) for p in EXPLICIT_TARGET_RE_PREFIXES)
|
|
|
|
|
|
def looks_like_imessage_target_id(target: str) -> bool:
|
|
return any(target.lower().startswith(p.lower()) for p in IMESSAGE_TARGET_PREFIXES)
|
|
|
|
|
|
def resolve_chat_type_from_target(target: str) -> ChatType:
|
|
parsed = parse_target(target)
|
|
value = parsed["value"]
|
|
if ";-;" in value or "@chat" in value:
|
|
return ChatType.GROUP
|
|
return ChatType.DIRECT
|