from __future__ import annotations import re from typing import Any _IRC_LINE_PATTERN = re.compile( r"^(?:@(?P[^ ]+) )?(?::(?P[^ ]+) )?(?P[a-zA-Z]+|\d{3})" r"(?: (?P.+?))?(?: :(?P.*))?$" ) _IRC_PREFIX_PATTERN = re.compile(r"^([^!@]+)(?:!([^@]+))?(?:@(.+))?$") def parse_irc_line(line: str) -> tuple[str | None, str, list[str]]: match = _IRC_LINE_PATTERN.match(line) if match is None: return None, line, [] command = match.group("command").upper() prefix = match.group("prefix") or None args: list[str] = [] params = match.group("params") or "" if params: args.extend(params.split()) trailing = match.group("trailing") if trailing is not None: args.append(trailing) return prefix, command, args def parse_irc_prefix(prefix: str | None) -> dict[str, str | None]: if not prefix: return {"nick": None, "user": None, "host": None} m = _IRC_PREFIX_PATTERN.match(prefix) if m is None: return {"nick": prefix, "user": None, "host": None} return { "nick": m.group(1) or None, "user": m.group(2) or None, "host": m.group(3) or None, } def extract_nick(prefix: str | None) -> str: if not prefix: return "unknown" return prefix.split("!")[0] def parse_irc_tags(line: str) -> dict[str, Any] | None: if not line.startswith("@"): return None space_idx = line.find(" ") if space_idx == -1: return None tag_str = line[1:space_idx] tags: dict[str, Any] = {} for tag in tag_str.split(";"): if "=" in tag: key, value = tag.split("=", 1) tags[key] = value else: tags[tag] = True return tags def parse_irc_tags_dict(line: str) -> dict[str, Any]: return parse_irc_tags(line) or {} def is_ctcp_message(text: str) -> bool: return text.startswith("\x01") and text.endswith("\x01") def parse_ctcp(text: str) -> tuple[str, str]: inner = text[1:-1] parts = inner.split(" ", 1) command = parts[0].upper() args = parts[1] if len(parts) > 1 else "" return command, args def format_ctcp(command: str, args: str = "") -> str: if args: return f"\x01{command} {args}\x01" return f"\x01{command}\x01" def extract_account_from_tags(tags: dict[str, Any]) -> str | None: return tags.get("account") or None def is_identified(tags: dict[str, Any]) -> bool: account = extract_account_from_tags(tags) return account is not None and account != "*"