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

76 lines
2.1 KiB
Python
Raw Normal View History

from __future__ import annotations
import re
from typing import Any
_E164_RE = re.compile(r"^\+[1-9]\d{1,14}$")
_NON_DIGIT_RE = re.compile(r"[^\d+]")
_PHONE_CLEAN_RE = re.compile(r"[\s\-\(\)\.]")
def normalize_e164(handle: str, default_country_code: str = "") -> str:
"""将电话号码标准化为 E.164 格式。
去除空格括号连字符补全国际区号
对已经是国际格式的号码保留 '+' 前缀
"""
clean = _PHONE_CLEAN_RE.sub("", handle.strip())
clean = _strip_service_prefixes(clean)
if not clean:
return handle
if clean.startswith("+"):
digits = clean[1:]
if digits.isdigit() and len(digits) <= 15:
return clean
return handle
if clean.startswith("00"):
digits = clean[2:]
if digits.isdigit() and len(digits) <= 15:
return f"+{digits}"
if clean.startswith("011"):
digits = clean[3:]
if digits.isdigit() and len(digits) <= 15:
return f"+{digits}"
if clean.isdigit() and default_country_code:
return f"+{default_country_code}{clean}"
if clean.isdigit() and len(clean) <= 15:
return f"+{clean}"
return handle
def _strip_service_prefixes(handle: str) -> str:
for prefix in ("imessage:", "sms:", "auto:"):
if handle.lower().startswith(prefix):
return handle[len(prefix) :]
return handle
def is_e164(handle: str) -> bool:
return bool(_E164_RE.match(handle))
def extract_digits(handle: str) -> str:
return _NON_DIGIT_RE.sub("", handle)
def parse_forwarded(data: dict) -> dict[str, Any] | None:
forwarded = data.get("forwarded")
if not forwarded:
return None
result: dict[str, Any] = {"is_forwarded": True}
if isinstance(forwarded, dict):
result["forwarded_from"] = forwarded.get("handle") or forwarded.get("sender", "")
result["forwarded_date"] = forwarded.get("date") or forwarded.get("originalDate", "")
elif isinstance(forwarded, bool) and forwarded:
result["forwarded_from"] = data.get("forwardedFrom", "")
return result