API-KA — plateforme centrale : collecte quotidienne des 8 services KA, historisation append-only et API publique sur www.api-ka.com
Python 60.9%
HTML 21%
TypeScript 7.3%
JavaScript 5.2%
CSS 4.8%
Shell 0.8%
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