from __future__ import annotations import logging import secrets import time from collections import OrderedDict logger = logging.getLogger(__name__) id_label = "matrixUserId" _pairing_codes: OrderedDict[str, tuple[str, float]] = OrderedDict() _PAIRING_MAX_SIZE = 10000 _PAIRING_TTL_SECONDS = 600 async def generate_code(peer_id: str, config: dict = None, account_id: str = None) -> str: alphabet = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789" code = "".join(secrets.choice(alphabet) for _ in range(8)) _evict_expired() _pairing_codes[peer_id] = (code, time.monotonic() + _PAIRING_TTL_SECONDS) if len(_pairing_codes) > _PAIRING_MAX_SIZE: _pairing_codes.popitem(last=False) logger.info("Generated pairing code for peer %s", peer_id) return code async def verify_code(peer_id: str, code: str, config: dict = None, account_id: str = None) -> bool: _evict_expired() stored = _pairing_codes.get(peer_id) if stored is None: logger.info("Pairing verify failed: no code for peer %s", peer_id) return False stored_code, expires_at = stored if time.monotonic() > expires_at: del _pairing_codes[peer_id] logger.info("Pairing verify failed: code expired for peer %s", peer_id) return False if code.upper() != stored_code: logger.info("Pairing verify failed: code mismatch for peer %s", peer_id) return False del _pairing_codes[peer_id] logger.info("Pairing verified for peer %s", peer_id) return True def _evict_expired() -> None: now = time.monotonic() expired = [k for k, (_, exp) in _pairing_codes.items() if now > exp] for k in expired: del _pairing_codes[k] def normalize_allow_entry(entry: str) -> str: return entry.strip().lower() async def notify_approval(config: dict, peer_id: str, account_id: str | None = None) -> None: logger.info("Matrix pairing approved for %s", peer_id)