نسخهٔ وب مستقل — پلتفرم نیروی کار هوش مصنوعی
مخزن اختصاصی برنامهٔ وب؛ محتوای پوشهٔ web در ریشهٔ مخزن قرار گرفت. تاریخچهٔ پروژهٔ ربات (agy-bot) در این مخزن وجود ندارد و هیچ وابستگی runtime به آن نیست.
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
"""Shared domain primitives.
|
||||
|
||||
Pure Python — no framework, no I/O. The domain layer must stay importable
|
||||
without FastAPI, SQLAlchemy or a database connection.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import uuid
|
||||
from datetime import UTC, datetime
|
||||
|
||||
_SLUG_RE = re.compile(r"[^a-z0-9]+")
|
||||
|
||||
|
||||
def new_id() -> str:
|
||||
"""Opaque, URL-safe entity id (portable across SQLite and PostgreSQL)."""
|
||||
return uuid.uuid4().hex
|
||||
|
||||
|
||||
def utcnow() -> datetime:
|
||||
return datetime.now(UTC)
|
||||
|
||||
|
||||
def slugify(value: str, *, max_length: int = 48) -> str:
|
||||
"""ASCII slug. Non-ASCII input (e.g. Persian) collapses to a stable fallback.
|
||||
|
||||
Persian organization names do not transliterate, so we keep a short random
|
||||
suffix appended by the caller when the slug would be empty.
|
||||
"""
|
||||
slug = _SLUG_RE.sub("-", value.strip().lower()).strip("-")
|
||||
slug = slug[:max_length].strip("-")
|
||||
if not slug:
|
||||
slug = f"x{uuid.uuid4().hex[:8]}"
|
||||
return slug
|
||||
|
||||
|
||||
def ensure_unique_slug(base: str, taken: set[str], *, max_length: int = 48) -> str:
|
||||
"""Append ``-2``, ``-3`` ... until the slug is free."""
|
||||
candidate = base[:max_length]
|
||||
if candidate not in taken:
|
||||
return candidate
|
||||
n = 2
|
||||
while True:
|
||||
suffix = f"-{n}"
|
||||
candidate = f"{base[: max_length - len(suffix)]}{suffix}"
|
||||
if candidate not in taken:
|
||||
return candidate
|
||||
n += 1
|
||||
Reference in New Issue
Block a user