""" Brandable generator (no external APIs). Generates pronounceable strings and checks availability via internal DomainChecker. """ from __future__ import annotations import asyncio import secrets from dataclasses import dataclass from app.services.domain_checker import domain_checker VOWELS = "aeiou" CONSONANTS = "bcdfghjklmnpqrstvwxz" def _rand_choice(alphabet: str) -> str: return alphabet[secrets.randbelow(len(alphabet))] def generate_cvcvc() -> str: return ( _rand_choice(CONSONANTS) + _rand_choice(VOWELS) + _rand_choice(CONSONANTS) + _rand_choice(VOWELS) + _rand_choice(CONSONANTS) ) def generate_cvccv() -> str: return ( _rand_choice(CONSONANTS) + _rand_choice(VOWELS) + _rand_choice(CONSONANTS) + _rand_choice(CONSONANTS) + _rand_choice(VOWELS) ) HUMAN_SUFFIXES = ["ly", "ri", "ro", "na", "no", "mi", "li", "sa", "ta", "ya"] def generate_human() -> str: # two syllable-ish: CV + CV + suffix base = _rand_choice(CONSONANTS) + _rand_choice(VOWELS) + _rand_choice(CONSONANTS) + _rand_choice(VOWELS) return base + HUMAN_SUFFIXES[secrets.randbelow(len(HUMAN_SUFFIXES))] @dataclass(frozen=True) class AvailabilityResult: domain: str is_available: bool | None status: str async def check_domains(domains: list[str], *, concurrency: int = 25) -> list[AvailabilityResult]: sem = asyncio.Semaphore(concurrency) async def _one(d: str) -> AvailabilityResult: async with sem: try: res = await domain_checker.check_domain(d, quick=True) return AvailabilityResult( domain=d, is_available=bool(res.is_available), status="available" if res.is_available else "taken", ) except Exception: return AvailabilityResult(domain=d, is_available=None, status="unknown") return list(await asyncio.gather(*[_one(d) for d in domains]))