import logging import random import string import time logger = logging.getLogger(__name__) CODE_TTL_SECONDS = 600 CODE_LENGTH = 6 MAX_GENERATE_PER_PEER_PER_MINUTE = 3 class FreshdeskPairing: def __init__(self): self._codes: dict[str, tuple[str, float]] = {} self._gen_timestamps: dict[str, list[float]] = {} async def generate_code(self, peer_id: str) -> str | None: now = time.time() timestamps = self._gen_timestamps.setdefault(peer_id, []) timestamps[:] = [ts for ts in timestamps if now - ts < 60] if len(timestamps) >= MAX_GENERATE_PER_PEER_PER_MINUTE: logger.warning("Pairing code rate limited for peer %s", peer_id) return None code = "".join(random.choices(string.digits, k=CODE_LENGTH)) self._codes[peer_id] = (code, now + CODE_TTL_SECONDS) timestamps.append(now) return code async def verify(self, peer_id: str, code: str) -> bool: now = time.time() entry = self._codes.get(peer_id) if entry is None: return False saved_code, expires_at = entry if now > expires_at: del self._codes[peer_id] return False return saved_code == code def cleanup(self): now = time.time() expired = [k for k, (_, exp) in self._codes.items() if now > exp] for k in expired: del self._codes[k]