"""Small, dependency-free helpers shared across modules.""" from __future__ import annotations import re from typing import Iterable, List def slugify(text: str, fallback: str = "video", max_len: int = 60) -> str: """Filesystem-safe, lowercase slug (e.g. for a video id derived from a URL).""" text = (text or "").strip().lower() slug = re.sub(r"[^a-z0-9]+", "_", text).strip("_") slug = slug[:max_len].strip("_") return slug or fallback def format_timestamp(seconds: float) -> str: """Return an ``HH:MM:SS`` label for a number of seconds.""" seconds = max(0, int(round(seconds))) h, rem = divmod(seconds, 3600) m, s = divmod(rem, 60) return f"{h:02d}:{m:02d}:{s:02d}" def extract_keywords(text: str, domain_terms: Iterable[str]) -> List[str]: """Return the domain terms that appear in ``text`` (case-insensitive). Multi-word terms are matched as substrings, which is robust to Thai-English code-switching where English keywords are embedded inside Thai sentences. The result preserves the order in which terms appear in ``domain_terms`` and contains no duplicates. """ if not text: return [] lowered = text.lower() found: List[str] = [] for term in domain_terms: t = term.lower().strip() if t and t in lowered and term not in found: found.append(term) return found def contains_any(text: str, phrases: Iterable[str]) -> List[str]: """Return every phrase from ``phrases`` that occurs in ``text``.""" if not text: return [] lowered = text.lower() return [p for p in phrases if p.lower() in lowered]