SPB Git forge

spb/house-ka

Public
18commits 1branches 0releases
1.9 MBsize
maindefault branch
19 days agolast push
Python 67% TypeScript 18.2% CSS 14.4%
4.1 KB · 93 lines python
Raw Blame History
1#!/usr/bin/env python32# -----------------------------------------------------------------------------3# House-Ka — Homes-for-sale aggregator (Canada outside Québec)4# Auteur : Simon-Pierre Boucher — contact@spboucher.ai5# run.py : point d'entrée — `sync`, `watch`, `serve`6# -----------------------------------------------------------------------------7"""Utilisation :8    python run.py sync [source ...]     # synchronise les propriétés9    python run.py watch [minutes]       # synchronise en boucle (défaut 60 min)10    python run.py serve [port]          # démarre l'API + le frontend (défaut 8090)11    python run.py list                  # liste les connecteurs enregistrés12    python run.py geocode [n]           # géocode les annonces sans coordonnées (max n requêtes)13    python run.py geocode-audit [n] [dry]  # audit coordonnées <-> ville (n = budget Nominatim)14    python run.py poi [n]               # commodités de proximité par immeuble (max n requêtes)15    python run.py quartier [n]          # rattache chaque annonce à son aire de diffusion (DAUID)16    python run.py mortgage-sync [slug…] # collecte les taux hypothécaires (toutes banques ou celles listées)17    python run.py mortgage-watch [min]  # collecte en boucle (défaut IMMOKA_MORTGAGE_INTERVAL_MIN=180)18    python run.py mortgage-status       # santé des providers de taux (OK/WARNING/ERROR)19"""20from __future__ import annotations2122import os23import sys24from pathlib import Path2526# Charger .env (FIRECRAWL_API_KEY, etc.) sans dépendance externe27_env = Path(__file__).parent / ".env"28if _env.exists():29    for line in _env.read_text().splitlines():30        line = line.strip()31        if line and not line.startswith("#") and "=" in line:32            k, _, v = line.partition("=")33            os.environ.setdefault(k.strip(), v.strip())343536def main() -> None:37    cmd = sys.argv[1] if len(sys.argv) > 1 else "serve"38    if cmd == "sync":39        from immoka import ingest40        ingest.run(sys.argv[2:] or None)41    elif cmd == "watch":42        from immoka import ingest43        minutes = int(sys.argv[2]) if len(sys.argv) > 2 else 6044        ingest.watch(minutes * 60)45    elif cmd == "list":46        from immoka.connectors import CONNECTORS47        for sid in sorted(CONNECTORS):48            print(sid)49        print(f"-- {len(CONNECTORS)} connecteur(s)")50    elif cmd == "geocode":51        from immoka import geocode52        geocode.run_batch(int(sys.argv[2]) if len(sys.argv) > 2 else None)53    elif cmd == "geocode1":   # ancien mode 1-par-1 (+ repli Nominatim)54        from immoka import geocode55        geocode.run(int(sys.argv[2]) if len(sys.argv) > 2 else None)56    elif cmd == "geocode-audit":   # cohérence coordonnées <-> ville annoncée57        from immoka import geocode58        budget = next((int(a) for a in sys.argv[2:] if a.isdigit()), None)59        geocode.run_audit(nominatim_budget=budget,60                          apply="dry" not in sys.argv[2:])61    elif cmd == "poi":62        from immoka import poi63        poi.run(int(sys.argv[2]) if len(sys.argv) > 2 else None)64    elif cmd == "quartier":65        from immoka import quartier66        quartier.enrich(int(sys.argv[2]) if len(sys.argv) > 2 else None)67    elif cmd == "mortgage-sync":68        from immoka.mortgage import scheduler69        scheduler.run(sys.argv[2:] or None)70    elif cmd == "mortgage-watch":71        from immoka.mortgage import scheduler72        minutes = int(sys.argv[2]) if len(sys.argv) > 2 else None73        scheduler.watch(minutes)74    elif cmd == "mortgage-status":75        from immoka.mortgage import store76        con = store.connect()77        for h in store.provider_health(con):78            print(f"{h['level']:8s} {h['provider']:15s} "79                  f"statut={h.get('status') or '-'} "80                  f"produits_courants={h.get('current_products', 0)} "81                  f"dernière_passe=il y a {h.get('age_minutes', '?')} min")82    elif cmd == "serve":83        import uvicorn84        port = int(sys.argv[2]) if len(sys.argv) > 2 else 809885        uvicorn.run("immoka.web:app", host="0.0.0.0", port=port)86    else:87        print(__doc__)88        sys.exit(1)899091if __name__ == "__main__":92    main()93