2026-08-24 01:18:40 +02:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import re
|
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
|
2026-08-25 00:08:57 +02:00
|
|
|
ADDRESS = re.compile(r"^[@#]([a-z0-9][a-z0-9._-]*):(?:[ \t]*)(.+)$", re.IGNORECASE)
|
2026-08-24 01:18:40 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
|
|
|
class RoutedMessage:
|
|
|
|
|
target_repo: str
|
|
|
|
|
body: str
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def parse_address_line(line: str) -> RoutedMessage | None:
|
|
|
|
|
"""Parse one complete direct-address line; ordinary input returns None."""
|
|
|
|
|
match = ADDRESS.match(line.rstrip("\r\n"))
|
|
|
|
|
if not match:
|
|
|
|
|
return None
|
|
|
|
|
return RoutedMessage(target_repo=match.group(1), body=match.group(2))
|