SPB Git forge

spb/api-ka

Public

API-KA — plateforme centrale : collecte quotidienne des 8 services KA, historisation append-only et API publique sur www.api-ka.com

48commits 1branches 0releases
5.9 MBsize
maindefault branch
19 days agolast push
Python 60.9% HTML 21% TypeScript 7.3% JavaScript 5.2% CSS 4.8% Shell 0.8%
2.4 KB · 65 lines python
Raw Blame History
1# ============================================2# Projet   : API-KA3# Fichier  : src/collectors/restoka_collector.py4# Node     : m3u96b5# Author   : Simon-Pierre Boucher6# Contact  : contact@spboucher.ai7# Date     : 2026-08-178# ============================================9"""Collecteur quotidien du service resto-ka (table restoka_data).1011Contrairement aux autres collecteurs, la liste ``/api/restaurants`` ne12contient que les métadonnées : les plats (menus → sections → items, avec13options et prix réels) ne sont exposés que sur la fiche détaillée14``/api/restaurants/{uid}``. Le fetch pagine donc la liste, puis récupère15la fiche complète de chaque restaurant — chaque enregistrement sauvegardé16contient ainsi le menu entier du jour.17"""1819from __future__ import annotations2021from typing import Any2223import httpx2425from src.collectors.base_collector import FETCH_TIMEOUT_SECONDS, BaseCollector262728class RestokaCollector(BaseCollector):29    """Collecte les restaurants ET leurs plats depuis RESTOKA_SOURCE_URL."""3031    service = "restoka"32    items_key = "restaurants"33    pagination = "offset"34    page_size = 500  # maximum accepté par l'API resto-ka (/api/restaurants)3536    def fetch(self) -> Any:37        """Récupère la liste paginée puis la fiche détaillée (plats inclus).3839        Returns:40            Liste des restaurants avec leur menu complet ; si une fiche41            détaillée est indisponible, l'enregistrement sommaire de la42            liste est conservé pour ne jamais perdre le restaurant.43        """44        summaries: list[dict[str, Any]] = super().fetch()45        detailed: list[dict[str, Any]] = []46        with httpx.Client(47            timeout=FETCH_TIMEOUT_SECONDS, follow_redirects=True48        ) as client:49            for summary in summaries:50                uid = summary.get("uid") if isinstance(summary, dict) else None51                if not uid:52                    detailed.append(summary)53                    continue54                try:55                    response = client.get(f"{self.source_url}/{uid}")56                    response.raise_for_status()57                    detailed.append(response.json())58                except httpx.HTTPError as exc:59                    self.logger.warning(60                        "Fiche détaillée indisponible, sommaire conservé",61                        extra={"uid": uid, "error": str(exc)},62                    )63                    detailed.append(summary)64        return detailed65