myYouTube/backend/app/core/slugify.py
vrubelroman 0ed20bb838 Implement Phases 1-5: skeleton, OAuth, categories, video sync/feed, playback
- FastAPI + PostgreSQL + Alembic + React/Vite skeleton, Docker Compose, healthcheck
- Google OAuth (single allowed account), encrypted refresh token storage
- Subscriptions sync with pagination, uploads playlist batch fetch
- Categories CRUD, many-to-many channel assignment, category filtering
- Video sync (playlistItems + videos.list batching), cached feed with cursor
  pagination, background scheduler (APScheduler)
- Video detail page with YouTube embed player
- SPA fallback routing, optimistic UI updates, client-side query caching

40 backend tests covering OAuth allow-list, sync idempotency, cascade deletes,
cursor pagination, and category filtering.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-16 18:44:30 +00:00

29 lines
938 B
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import re
_CYRILLIC_MAP = {
"а": "a", "б": "b", "в": "v", "г": "g", "д": "d", "е": "e", "ё": "e",
"ж": "zh", "з": "z", "и": "i", "й": "y", "к": "k", "л": "l", "м": "m",
"н": "n", "о": "o", "п": "p", "р": "r", "с": "s", "т": "t", "у": "u",
"ф": "f", "х": "h", "ц": "ts", "ч": "ch", "ш": "sh", "щ": "sch", "ъ": "",
"ы": "y", "ь": "", "э": "e", "ю": "yu", "я": "ya",
}
def _transliterate(text: str) -> str:
return "".join(_CYRILLIC_MAP.get(ch, ch) for ch in text)
def slugify(text: str) -> str:
text = _transliterate(text.lower())
text = re.sub(r"[^a-z0-9]+", "-", text).strip("-")
return text or "category"
def unique_slugify(text: str, existing_slugs: set[str]) -> str:
base = slugify(text)
if base not in existing_slugs:
return base
suffix = 2
while f"{base}-{suffix}" in existing_slugs:
suffix += 1
return f"{base}-{suffix}"