SPB Git

spb/ora-ka Public

Ora-Ka — cinq agrégateurs Ka, une barre de recherche hybride (exact + sémantique)

Python 80% TypeScript 12.9% CSS 6.8%
2.3 KB · 67 lines python
Raw Blame History
1# -----------------------------------------------------------------------------2# Ora-Ka — Plateforme unifiée des agrégateurs Ka3# Auteur : Simon-Pierre Boucher — contact@spboucher.ai4# hubfav.py : « Mon univers Ka » — lecture des favoris unifiés du membre depuis5#   le magasin central du hub Groupe KA (toutes plateformes : Lou·Ka, Immo·Ka,6#   Auto·Ka, Fabri·Ka, Food·Ka…). GET signé HMAC du secret SSO partagé,7#   scope=all. Cache mémoire 30 s par ka_id ; toute erreur → liste vide8#   (l'affichage est un bonus, jamais bloquant).9#   Config .env : KA_SSO_SECRET, KA_HUB_URL (optionnel).10# -----------------------------------------------------------------------------11from __future__ import annotations1213import hashlib14import hmac15import os16import threading17import time1819import requests2021CLIENT_ID = "ora-ka"22KA_HUB_URL = os.environ.get("KA_HUB_URL", "https://www.groupe-ka.com").rstrip("/")23CACHE_TTL = 30.0    # secondes — le hub reste la source de vérité2425_cache: dict[str, tuple[float, list]] = {}26_cache_lock = threading.Lock()272829def _sig(ka_id: str, ts: int) -> str | None:30    secret = os.environ.get("KA_SSO_SECRET")31    if not secret:32        return None33    return hmac.new(secret.encode(),34                    f"{CLIENT_ID}.{ka_id}.{ts}".encode(),35                    hashlib.sha256).hexdigest()363738def hub_list_all(ka_id: str | None) -> list:39    """Tous les favoris du membre (toutes plateformes du groupe), ou []."""40    if not ka_id or not str(ka_id).startswith("ka-"):41        return []    # compte legacy non relié au hub42    ka_id = str(ka_id)43    now = time.time()44    with _cache_lock:45        hit = _cache.get(ka_id)46        if hit and now - hit[0] < CACHE_TTL:47            return hit[1]48    ts = int(now)49    sig = _sig(ka_id, ts)50    if not sig:51        return []52    try:53        r = requests.get(f"{KA_HUB_URL}/api/sso/favorites", timeout=5, params={54            "client_id": CLIENT_ID, "ka_id": ka_id,55            "ts": str(ts), "sig": sig, "scope": "all",56        })57        if not r.ok:58            return []59        favs = r.json().get("favorites") or []60        if not isinstance(favs, list):61            return []62    except Exception:63        return []    # best-effort : la landing s'affiche simplement sans la section64    with _cache_lock:65        _cache[ka_id] = (now, favs)66    return favs67