SPB Git forge

spb/house-ka

Public
18commits 1branches 0releases
1.9 MBsize
maindefault branch
19 days agolast push
Python 67% TypeScript 18.2% CSS 14.4%
3.2 KB · 76 lines python
Raw Blame History
1# -----------------------------------------------------------------------------2# Immo-Ka — Agrégateur de propriétés à vendre (province de Québec)3# Auteur : Simon-Pierre Boucher — contact@spboucher.ai4# favorites.py : routes API des favoris (♥) — session Groupe KA requise.5#   AUCUN stockage local : lecture et écriture passent par le hub Groupe KA6#   (magasin central « Mon univers Ka »), voir immoka/hubfav.py.7#     GET  /api/favorites        -> {ids:[item_id…], items:[…]}   (depuis le hub)8#     POST /api/favorites/toggle  {on:bool, item:{item_id,title,…}} -> {ok,on}9#   401 si pas de session, ou si le compte n'est pas relié au hub (pas de10#   ka_id) — le frontend redirige alors vers /api/auth/ka/login.11# -----------------------------------------------------------------------------12from __future__ import annotations1314from fastapi import APIRouter, Request15from fastapi.responses import JSONResponse1617from .auth import current_user18from .hubfav import hub_list, hub_toggle, invalidate1920router = APIRouter(prefix="/api/favorites")2122# champs acceptés d'un item de favori (et longueur maximale)23_ITEM_FIELDS = {"item_id": 120, "title": 200, "subtitle": 200,24                "price_label": 60, "image_url": 500, "url": 500}252627def _ka_id(request: Request) -> str | None:28    """KA-ID de la session, ou None (pas de session / compte non relié)."""29    user = current_user(request)30    if not user:31        return None32    ka_id = str(user.get("ka_id") or "")33    return ka_id if ka_id.startswith("ka-") else None343536@router.get("")37def list_favorites(request: Request):38    """Favoris immo-ka du membre connecté, lus du hub Groupe KA."""39    ka_id = _ka_id(request)40    if not ka_id:41        return JSONResponse({"error": "non connecté"}, status_code=401)42    items = hub_list(ka_id)43    return {"ids": [it.get("item_id") for it in items if it.get("item_id")],44            "items": items}454647@router.post("/toggle")48async def toggle_favorite(request: Request):49    """Ajoute (on=true) ou retire (on=false) un favori — poussé au hub."""50    ka_id = _ka_id(request)51    if not ka_id:52        return JSONResponse({"error": "non connecté"}, status_code=401)53    try:54        body = await request.json()55        assert isinstance(body, dict)56    except Exception:57        return JSONResponse({"error": "corps JSON attendu"}, status_code=400)58    on = bool(body.get("on"))59    raw = body.get("item") or {}60    item = {k: str(raw.get(k) or "")[:n] for k, n in _ITEM_FIELDS.items()}61    if not item["item_id"]:62        return JSONResponse({"error": "item.item_id requis"}, status_code=400)63    ok = hub_toggle(ka_id, "add" if on else "remove", item)64    # signal fort du moteur de préférences KA ID (features lues de la BD)65    from . import db as _db, kaid as _kaid66    con = _db.connect()67    row = con.execute("SELECT * FROM listings WHERE uid=?",68                      (item["item_id"],)).fetchone()69    con.close()70    from .web import _kaid_features as _feats71    _kaid.track({"ka_id": ka_id}, "favorite" if on else "unfavorite",72                entity_type="property", entity_id=item["item_id"],73                features=_feats(dict(row)) if row else None)74    invalidate(ka_id)   # le prochain GET relit l'état frais du hub75    return {"ok": ok, "on": on}76