# ----------------------------------------------------------------------------- # Immo-Ka — Agrégateur de maisons à vendre (province de Québec) # Auteur : Simon-Pierre Boucher — contact@spboucher.ai # connectors/agences_source_immo.py : agences INDÉPENDANTES sur la plateforme # source.immo (plugin WordPress). Beaucoup de petites/moyennes agences QC # l'utilisent (liste sur source.immo). Chacune expose sa config publique à # /wp-content/uploads/_sourceimmo/_configs.json → on lit l'API publique # api-v1.source.immo (voir SourceImmoConnector). Ce sont des agences # autonomes : leurs inscriptions (leur propre n° Centris) sont ADDITIVES — # pas de sous-agence d'une bannière déjà couverte → source_id normal (pas _ag_). # # Un connecteur par agence est généré depuis data/source_immo_agencies.json. # ----------------------------------------------------------------------------- from __future__ import annotations import json from pathlib import Path from .sourceimmo import SourceImmoConnector from ..schema import PropertyListing REGISTRY = Path(__file__).resolve().parent.parent.parent / "data" / "source_immo_agencies.json" class _AgenceSourceImmo(SourceImmoConnector): """Agence indépendante source.immo. Recharge sa config depuis le site (résilient aux rotations d'UUID) ; agency_name pour l'affichage Sources.""" agency_name = "" def fetch(self) -> list[PropertyListing]: base = self.site_url.rstrip("/") try: cfg = self.get(f"{base}/wp-content/uploads/_sourceimmo/_configs.json").json() self.account_id = cfg.get("account_id", self.account_id) self.api_key = cfg.get("api_key", self.api_key) self.app_id = cfg.get("app_id", self.app_id) self.view_id = cfg.get("default_view", self.view_id) except Exception: pass return super().fetch() def _to_listing(self, it: dict) -> PropertyListing | None: lst = super()._to_listing(it) if lst is not None: lst.broker_name = self.agency_name lst.agency = self.agency_name ref = it.get("ref_number") or it.get("id") if ref and self.site_url: lst.url = f"{self.site_url.rstrip('/')}/propriete/{ref}" return lst def _load() -> list[dict]: try: return json.loads(REGISTRY.read_text(encoding="utf-8")) except Exception: return [] # Génère une classe par agence du registre. for _ag in _load(): if not all(_ag.get(k) for k in ("id", "domain", "account", "api", "app", "view")): continue _sid = _ag["id"] _dom = _ag["domain"].rstrip("/") globals()[f"AGENCE_{_sid.upper()}"] = type( "AgenceSI" + "".join(p.title() for p in _sid.split("_")), (_AgenceSourceImmo,), { "source_id": _sid, "account_id": _ag["account"], "api_key": _ag["api"], "app_id": _ag["app"], "view_id": _ag["view"], "site_url": f"https://{_dom}/", "agency_name": _ag.get("name", _sid.title()), }, )