from __future__ import annotations _IRC_PROTOCOL_PREFIX = "irc:" def resolve_chat_id(target: str, sender_nick: str) -> str: is_channel = target.startswith("#") or target.startswith("&") return target if is_channel else f"dm_{sender_nick}" def resolve_channel_user_id(nick: str) -> str: return nick def resolve_thread_id(agent_id: str, chat_id: str) -> str: is_channel = chat_id.startswith("#") or chat_id.startswith("&") if is_channel: channel_name = chat_id.lstrip("#&") return f"agent:{agent_id}:irc:channel:{channel_name}" dm_nick = chat_id.removeprefix("dm_") return f"agent:{agent_id}:irc:dm:{dm_nick}" def is_channel(target: str) -> bool: return target.startswith("#") or target.startswith("&") def normalize_irc_messaging_target(target: str) -> dict[str, str] | None: """Parse IRC messaging target with optional protocol prefix. Handles: - raw channel: ``#channel``, ``&channel`` - protocol prefix: ``irc:channel:#channel``, ``irc:user:nick`` - DM target: plain nick (no prefix) Returns ``{"kind": "group"|"user", "target": "..."}`` or None. """ clean = target.strip() if not clean: return None if clean.startswith(_IRC_PROTOCOL_PREFIX): clean = clean.removeprefix(_IRC_PROTOCOL_PREFIX) if clean.startswith("channel:"): ch = clean.removeprefix("channel:") if ch: return {"kind": "group", "target": ch} return None if clean.startswith("user:"): u = clean.removeprefix("user:") if u: return {"kind": "user", "target": u} return None return None if clean.startswith("#") or clean.startswith("&"): return {"kind": "group", "target": clean} return {"kind": "user", "target": clean} def resolve_targets(kind: str, target: str) -> dict[str, str] | None: """Resolve a target string based on its kind. - ``kind="group"``: auto-prepend ``#`` if missing, reject bare nick. - ``kind="user"``: reject channel targets (``#``/``&``). Returns ``{"kind": "...", "target": "..."}`` or None on error. """ t = target.strip() if not t: return None if kind == "group": if not t.startswith("#") and not t.startswith("&"): t = f"#{t}" return {"kind": "group", "target": t} if kind == "user": if t.startswith("#") or t.startswith("&"): return None return {"kind": "user", "target": t} return None