"""Utilities for invite code generation and validation.""" import random from pathlib import Path # Load BIP39 words from file _WORDS_FILE = Path(__file__).parent / "words.txt" with open(_WORDS_FILE) as f: BIP39_WORDS = [line.strip() for line in f if line.strip()] assert len(BIP39_WORDS) == 2048, f"Expected 2048 BIP39 words, got {len(BIP39_WORDS)}" def generate_invite_identifier() -> str: """ Generate a unique invite identifier. Format: word1-word2-NN where: - word1, word2 are random BIP39 words - NN is a two-digit number (00-99) Returns lowercase identifier. """ word1 = random.choice(BIP39_WORDS) word2 = random.choice(BIP39_WORDS) number = random.randint(0, 99) return f"{word1}-{word2}-{number:02d}" def normalize_identifier(identifier: str) -> str: """ Normalize an invite identifier for comparison/lookup. - Converts to lowercase - Strips whitespace """ return identifier.strip().lower() def is_valid_identifier_format(identifier: str) -> bool: """ Check if an identifier has valid format (word-word-NN). Does NOT check if words are valid BIP39 words. """ parts = identifier.split("-") if len(parts) != 3: return False word1, word2, number = parts # Check words are non-empty if not word1 or not word2: return False # Check number is two digits if len(number) != 2 or not number.isdigit(): return False return True