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