SPB Git

spb/ora-ka Public

Ora-Ka — cinq agrégateurs Ka, une barre de recherche hybride (exact + sémantique)

Python 80% TypeScript 12.9% CSS 6.8%
3.0 KB · 78 lines python
Raw Blame History
1# -----------------------------------------------------------------------------2# Immo-Ka — Agrégateur de maisons à vendre (province de Québec)3# Auteur : Simon-Pierre Boucher — contact@spboucher.ai4# connectors/agences_source_immo.py : agences INDÉPENDANTES sur la plateforme5#   source.immo (plugin WordPress). Beaucoup de petites/moyennes agences QC6#   l'utilisent (liste sur source.immo). Chacune expose sa config publique à7#   /wp-content/uploads/_sourceimmo/_configs.json → on lit l'API publique8#   api-v1.source.immo (voir SourceImmoConnector). Ce sont des agences9#   autonomes : leurs inscriptions (leur propre n° Centris) sont ADDITIVES —10#   pas de sous-agence d'une bannière déjà couverte → source_id normal (pas _ag_).11#12#   Un connecteur par agence est généré depuis data/source_immo_agencies.json.13# -----------------------------------------------------------------------------14from __future__ import annotations1516import json17from pathlib import Path1819from .sourceimmo import SourceImmoConnector20from ..schema import PropertyListing2122REGISTRY = Path(__file__).resolve().parent.parent.parent / "data" / "source_immo_agencies.json"232425class _AgenceSourceImmo(SourceImmoConnector):26    """Agence indépendante source.immo. Recharge sa config depuis le site27    (résilient aux rotations d'UUID) ; agency_name pour l'affichage Sources."""2829    agency_name = ""3031    def fetch(self) -> list[PropertyListing]:32        base = self.site_url.rstrip("/")33        try:34            cfg = self.get(f"{base}/wp-content/uploads/_sourceimmo/_configs.json").json()35            self.account_id = cfg.get("account_id", self.account_id)36            self.api_key = cfg.get("api_key", self.api_key)37            self.app_id = cfg.get("app_id", self.app_id)38            self.view_id = cfg.get("default_view", self.view_id)39        except Exception:40            pass41        return super().fetch()4243    def _to_listing(self, it: dict) -> PropertyListing | None:44        lst = super()._to_listing(it)45        if lst is not None:46            lst.broker_name = self.agency_name47            lst.agency = self.agency_name48            ref = it.get("ref_number") or it.get("id")49            if ref and self.site_url:50                lst.url = f"{self.site_url.rstrip('/')}/propriete/{ref}"51        return lst525354def _load() -> list[dict]:55    try:56        return json.loads(REGISTRY.read_text(encoding="utf-8"))57    except Exception:58        return []596061# Génère une classe par agence du registre.62for _ag in _load():63    if not all(_ag.get(k) for k in ("id", "domain", "account", "api", "app", "view")):64        continue65    _sid = _ag["id"]66    _dom = _ag["domain"].rstrip("/")67    globals()[f"AGENCE_{_sid.upper()}"] = type(68        "AgenceSI" + "".join(p.title() for p in _sid.split("_")),69        (_AgenceSourceImmo,),70        {71            "source_id": _sid,72            "account_id": _ag["account"], "api_key": _ag["api"],73            "app_id": _ag["app"], "view_id": _ag["view"],74            "site_url": f"https://{_dom}/",75            "agency_name": _ag.get("name", _sid.title()),76        },77    )78