# -*- coding: utf-8 -*- """Étape 7 — visuels de démonstration, créés en ressources et rattachés. `POST /api/Resource/upload` ne stocke aucun octet : il lit le fichier, l'encode en base64, jette le résultat, et n'enregistre que le libellé, le chemin de bucket et la taille. Le blob est déposé dans Firebase Storage par `manager-app` depuis le navigateur — un script qui parle à l'API ne peut pas l'y écrire. Les ressources sont donc créées en type `ImageUrl`, servies par `serve_images.py`. **Ce serveur doit tourner pendant les captures.** Idempotent : une ressource déjà créée sous le même libellé est réutilisée. """ import json from pathlib import Path from api import Api STATE = Path(__file__).resolve().parent / "state.json" IMAGES = Path(__file__).resolve().parent / "images" HOST = "http://localhost:8099" IMAGE_URL = 2 # ResourceType.ImageUrl — hors bucket, donc hors quota SECTION_IMAGES = { "Mosaïque de Vichten": "art-vichten", "Goeblange-Nospelt": "art-goeblange", "Villeroy & Boch Art déco": "art-villeroy", "Cabinet des médailles": "art-medailles", "Fort Thüngen": "art-thungen", "Démantèlement 1867": "art-demantelement", "Maquettes et plans-reliefs": "art-maquettes", "La villa romaine": "art-villa", "Thermes et hypocauste": "art-thermes", "Parcours extérieur": "parcours-echternach", "Sur les pas du maître": "parcours-echternach", "Le secret de la villa": "parcours-escape", "Collections": "site-feschmaart", "Quiz archéologie": "art-vichten", "Expositions et rendez-vous": "site-feschmaart", } CONFIG_IMAGES = { "feschmaart": "site-feschmaart", "draieechelen": "site-draieechelen", "echternach": "site-echternach", } POI_IMAGES = { "Entrée du site": "poi-entree", "Cour intérieure": "poi-cour", "Les thermes": "poi-thermes", "Les bassins": "poi-bassins", "Point de vue sur la Sûre": "poi-panorama", } def sync_resources(api, instance_id): """Une ressource ImageUrl par PNG. Les lignes laissées sans `url` par `upload` sont corrigées sur place plutôt que supprimées : elles gardent leur identifiant, donc les rattachements déjà posés restent valides — et la suppression d'une ressource échoue de toute façon tant que le correctif de `ResourceController` n'est pas déployé. """ existing = {r["label"]: r for r in (api.get(f"/api/Resource?instanceId={instance_id}") or [])} for label, resource in existing.items(): if resource.get("url") or not (IMAGES / f"{label}.png").exists(): continue resource["type"] = IMAGE_URL resource["url"] = f"{HOST}/{label}.png" resource["sizeBytes"] = (IMAGES / f"{label}.png").stat().st_size api.put("/api/Resource", resource) print(f" ~ {label} (URL ajoutée)") existing = {r["label"]: r for r in (api.get(f"/api/Resource?instanceId={instance_id}") or [])} resources = {} for path in sorted(IMAGES.glob("*.png")): if path.name.startswith("_"): continue label = path.stem if label in existing: resources[label] = existing[label] print(f" = {label}") continue created = api.post("/api/Resource", { "instanceId": instance_id, "label": label, "type": IMAGE_URL, "url": f"{HOST}/{path.name}", "sizeBytes": path.stat().st_size, }) resources[label] = created print(f" + {label}") return resources def main(): api = Api() state = json.loads(STATE.read_text(encoding="utf-8")) instance_id = state["instanceId"] print("ressources") resources = sync_resources(api, instance_id) print("\nsites") for key, image in CONFIG_IMAGES.items(): resource = resources[image] config = api.get(f"/api/Configuration/{state['configs'][key]}") config["imageId"] = resource["id"] config["imageSource"] = resource["url"] api.put("/api/Configuration", config) print(f" {key} <- {image}") print("\nsections") for key, config_id in state["configs"].items(): for section in api.get(f"/api/Section/configuration/{config_id}") or []: image = SECTION_IMAGES.get(section["label"]) if not image: continue resource = resources[image] detail = api.get(f"/api/Section/{section['id']}") if detail.get("imageSource") == resource["url"]: print(f" = {section['label']}") continue detail["imageId"] = resource["id"] detail["imageSource"] = resource["url"] api.put("/api/Section", detail) print(f" + {section['label']} <- {image}") print("\nétape 7 terminée — points d'intérêt et applications : step7b_finish.py") if __name__ == "__main__": main()