Système d'import automatique de publications
Objectif
Récupérer automatiquement les publications (actualités, événements) depuis les sites web des mairies et les insérer dans la base DMV.
Architecture
ImportSource (config en DB)
└── ImportConnectorInterface (parsing HTML/RSS)
└── ImportRunnerService (orchestration, déduplication, insertion)
└── publications (table Supabase)
Connecteurs disponibles
parser_key | Description |
|---|---|
bessan_fr | Agenda/événements de bessan.fr (endpoint AJAX agenda) |
bessan_fr_actu | Actualités de bessan.fr (endpoint AJAX actualités) |
Modèle ImportSource
Chaque source est une ligne dans la table import_sources.
| Champ | Type | Description |
|---|---|---|
key | string | Identifiant court unique (ex : bessan_fr_actu) |
parser_key | string | Connecteur PHP à utiliser |
commune_id | uuid | Commune cible |
acteur_id | uuid | Acteur associé aux publications créées |
type_id | uuid | Type de publication (actualité, événement…) |
scope | string | local / public |
auto_publish | bool | Auto-publication si toutes les conditions sont remplies |
require_image | bool | Publication refusée si pas d'image valide |
require_date | bool | Publication refusée si pas de date_debut |
schedule_cron | string | Expression cron (ex : 0 6 * * *) |
Logique de modération à l'import
ImportRunnerService::resolveModeration() retourne 'published' ou 'pending'
selon les conditions suivantes. Toutes doivent être vraies pour auto-publier :
auto_publish = truesource_urlprésente dans l'item parséacteur_idconfiguré sur la sourcetype_idconfiguré sur la source- Si
require_image = true: image HTTP valide dans l'item - Si
require_date = true:date_debutprésente dans l'item
Si moderation_status = 'pending' :
valide = falsepublie_le = null→ publication invisible sur tous les fronts
Les actualités mairie n'ont pas de date_debut. Si require_date = true sur
la source, toutes les actualités seront créées en pending et resteront
invisibles tant qu'elles ne sont pas validées manuellement dans le backoffice.
Déduplication
Stratégie configurée par dedupe_strategy sur la source. Le runner compare
source_url des items entrants avec les publications existantes pour éviter
les doublons à l'import.
Si deux imports successifs ont lieu (ex. import manuel + cron), des doublons
de contenu peuvent apparaître en base avec des id différents. Le frontend
DMV Public applique une déduplication de présentation par clé
titre normalisé | date (voir section Frontend).
Endpoints admin
| Méthode | Route | Description |
|---|---|---|
GET | /api/v1/admin/import-sources | Liste toutes les sources |
POST | /api/v1/admin/import-sources | Créer une source |
GET | /api/v1/admin/import-sources/{id} | Lire une source |
PATCH | /api/v1/admin/import-sources/{id} | Modifier une source |
DELETE | /api/v1/admin/import-sources/{id} | Supprimer une source |
POST | /api/v1/admin/import-sources/{id}/run | Import manuel (?dry_run=true pour test) |
GET | /api/v1/admin/import-sources/{id}/runs | Historique des runs |
GET | /api/v1/admin/import-sources/{id}/logs/{date} | Log d'un run (YYYY-MM-DD) |
Tous ces endpoints nécessitent identify.app + auth:sanctum + ensure.admin.
Le listing GET /api/v1/admin/import-sources renvoie en plus :
type_nom: libellé du type de publication liéacteur_nom: libellé de l'acteur lié
Format d'un run log
2026-06-22 18:27:00 [INFO] === Import bessan_fr_actu → DMV ===
2026-06-22 18:27:00 [INFO] Source : Actualités Bessan (id=xxx)
2026-06-22 18:27:00 [INFO] auto_publish=true, require_image=false, require_date=false
2026-06-22 18:27:01 [INFO] 35 actualité(s) trouvée(s) sur la source.
2026-06-22 18:27:05 [INFO] [CRÉÉ] UN NOUVEAU SITE INTERNET — status=published
2026-06-22 18:27:05 [INFO] [SKIP] RÉSULTATS DES ÉLECTIONS — déjà en base
2026-06-22 18:27:06 [INFO] === Fin : 12 créé(s) | 23 skip(s) | 0 erreur(s) — success ===
Points de vigilance
acteur_idobligatoire pour l'auto-publication. S'il est absent, toutes les publications tombent enpending.publie_leest fixé ànow()seulement à la création simoderation_status = 'published'. Une validation manuelle ultérieure dans le backoffice le fixe également depuis le 2026-06-26.- Si une publication existe déjà pour la même
source_url, le runner peut compléterimage_urllorsqu'elle manque et réalignertype_idsur la configuration courante de la source. - Les imports multiples sur la même source peuvent créer des doublons si la
déduplication par
source_urlne fonctionne pas (URL absente ou modifiée).