Some checks failed
CI / Frontend Lint & Type Check (push) Has been cancelled
CI / Frontend Build (push) Has been cancelled
CI / Backend Lint (push) Has been cancelled
CI / Backend Tests (push) Has been cancelled
CI / Docker Build (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
Deploy / Build & Push Images (push) Has been cancelled
Deploy / Deploy to Server (push) Has been cancelled
Deploy / Notify (push) Has been cancelled
Adds HUNT (Sniper/Trend/Forge), CFO dashboard (burn rate + kill list), and a plugin-based Analyze side panel with caching and SSRF hardening.
77 lines
2.0 KiB
Python
77 lines
2.0 KiB
Python
"""
|
|
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]))
|
|
|