|
|
## L'architecture en 30 secondes
```
connecteurs (1 module / source) normalisation (Event) SQLite (diff + grâce)
sortika/connectors/*.py → schema.py + normalize.py → db.py
▲ auto-découverts + regions.py (MAMH) │
│ ▼
watcher horaire (PM2) frontend SPA + fiches ← API FastAPI + SSR SEO
ingest.py watch frontend/index.html web.py + seo.py
```
| Couche | Rôle | Fichiers |
|---|---|---|
| **Connecteurs** | 1 module Python par source : API JSON internes (Algolia evenko, Tourinsoft, CKAN), listes HTML, Scrapfly (Cloudflare), caches incrémentaux | `sortika/connectors/*.py` |
| **Schéma** | `Event` standardisé : titre, catégories canoniques, lieu, ville, **région (17)**, lat/lng, dates ISO, gratuité/prix avec `price_label` source | `sortika/schema.py` |
| **Normalisation** | dates FR/ISO, prix, catégories (14), villes, entités HTML | `sortika/normalize.py` |
| **Régions** | Répertoire des municipalités MAMH : 1 250 villes + arrondissements + alias, homonymes résolus par population | `sortika/regions.py` + `data/villes_regions.json` |
| **Persistance** | upsert par hash de contenu, délai de grâce 2 syncs, alerte de dérive, historique de syncs | `sortika/db.py` |
| **Dédup** | empreinte titre + ville + date : un même concert publié par 3 sources = **une carte**, la fiche la plus riche gagne | `schema.dedup_key()` + `web.py` |
| **API + SSR** | recherche/filtres JSON, fiches `/evenement/{uid}` servies avec `` unique + **JSON-LD Event**, robots, sitemaps | `sortika/web.py` + `sortika/seo.py` |
| **Frontend** | SPA sans build, routeur History API, design system **Groupe KA « éditorial sharp »** | `frontend/index.html` |
## Les 8 connecteurs actifs
| Source | Type / accès | Extraction | Volume |
|---|---|---|---|
| **Le point de vente** | billetterie QC — robots `Allow: *` | listes HTML paginées (~65 pages) | ~2 500 concerts, humour, théâtre — toute la province |
| **SIT Québec** (Ministère du Tourisme) | données ouvertes CC 4.0 | API JSON Tourinsoft | ~1 600 événements touristiques, toutes les régions |
| **Ville de Montréal** | données ouvertes CC BY 4.0 | API CKAN datastore | ~5 600 événements municipaux |
| **evenko** | promoteur — robots `Allow: /api/search*` | proxy Algolia percé (`body=base64({params:[q,opts],lang})`) | ~460 grands concerts (Centre Bell, Place Bell, MTELUS…) |
| **La Vitrine** | Content-Signal `search=yes, use=reference` | sitemap + fiches HTML (dates de tournée dédupliquées par id de représentation), cache incrémental | ~5 100 représentations |
| **Atuvu.ca** | Cloudflare → **Scrapfly**, robots `Allow: /` | sitemaps lastmod + fiches, cache incrémental plafonné | rattrapage progressif |
| **Ville de Sherbrooke** | calendrier municipal public | JSON embarqué `TRANSFER_CACHE` — 1 requête | ~270 événements avec images et gratuité |
| **Ville de Laval** | données ouvertes CC 4.0 | JSON officiel | ~290 activités |
Sources écartées après vérification (jeux périmés) : Longueuil (2017), Saguenay (2022),
Repentigny (2021) — consignées au registre `data/sources.json` avec leur statut.
## Démarrage rapide
```bash
python3 -m venv .venv && .venv/bin/pip install -r requirements.txt
.venv/bin/python -m pytest tests/ -q # 19 tests (fixtures réelles, zéro réseau)
.venv/bin/python run.py sync # ingestion des 8 sources
.venv/bin/python run.py web --port 8120 # API + frontend + SSR
.venv/bin/python run.py watch --interval 3600 # boucle d'ingestion horaire
```
Secrets : `SCRAPFLY_API_KEY` dans `.env` (requis seulement pour Atuvu).
## API
| Route | Description |
|---|---|
| `GET /api/events` | recherche — `q`, `region`, `city`, `category`, `free`, `from`, `to`, `sort`, pagination ; dédupliquée inter-sources |
| `GET /api/events/{uid}` | fiche complète d'un événement |
| `GET /api/stats` | volumes par région et par catégorie |
| `GET /api/sources` | registre des sources + événements actifs + dernière synchro |
| `GET /evenement/{uid}` | fiche HTML SSR (title/og/canonical + **JSON-LD Event**) |
| `GET /sitemap.xml` · `/robots.txt` | référencement |
| `GET /docs` | Swagger |
## Production
Nœud **M3U96a** (MacLustr) — PM2 : `sorti-ka-web` (uvicorn :8120),
`sorti-ka-sync` (watch **horaire** — mise à jour continue), `sorti-ka-ngrok`
(`www.sorti-ka.com`). Registre : `~/Desktop/cluster-skill/cluster-deployments.json`.
## Principes
1. **Index fidèle** — rien d'inventé : prix et dates viennent de la source, avec
`price_label` original conservé et attribution systématique.
2. **Sources légitimes d'abord** — données ouvertes officielles et sites au
robots.txt permissif ; CGU/licences consignées en tête de chaque connecteur.
3. **Travail de moine** — un connecteur robuste à la fois, testé sur fixtures
réelles, avec alerte de dérive quand une source casse.
4. **Cohérence ·Ka** — architecture Lou·Ka, design system Groupe KA.
---
© 2026 Sorti·Ka — Simon-Pierre Boucher \