from __future__ import annotations import re _E164_CLEAN = re.compile(r"[^\d+]") def normalize_imessage_handle(handle: str) -> str: handle = handle.strip() for prefix in ("imessage:", "sms:", "auto:"): if handle.lower().startswith(prefix): handle = handle[len(prefix):] if "@" in handle: return handle.lower().strip() return normalize_e164(handle) def normalize_e164(handle: str) -> str: cleaned = _E164_CLEAN.sub("", handle) if not cleaned: return handle if not cleaned.startswith("+"): cleaned = "+" + cleaned return cleaned def parse_target(target: str) -> tuple[str, str | None]: """Parse a target string into (format, value).""" target = target.strip() if target.startswith("chat_guid:"): return ("chat_guid", target[len("chat_guid:"):]) if target.startswith("chat_identifier:"): return ("chat_identifier", target[len("chat_identifier:"):]) return ("handle", normalize_imessage_handle(target)) def build_session_key( channel_type: str, account_id: str, chat_type: str, identifier: str, ) -> str: return f"{channel_type}:{account_id}:{chat_type}:{identifier}" def parse_session_key(session_key: str) -> dict | None: parts = session_key.split(":") if len(parts) < 4: return None return { "channel_type": parts[0], "account_id": parts[1], "chat_type": parts[2], "identifier": ":".join(parts[3:]), }