ForcePilot/backend/package/yuxi/channels/adapters/imessage/targets.py

86 lines
2.3 KiB
Python
Raw Normal View History

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