Files
echo-du-huit/docs/RECHERCHE.md
T

8.4 KiB

Recherche technique — faits vérifiés (2026-06-29)

Document de référence pour l'implémentation. Toutes les valeurs ci-dessous sont vérifiées sur le HTML/ICS réel, pas supposées. Re-vérifier si > 6 mois.


1. Source : calendrier Nextcloud (CalDAV)

  • URL : https://atelier-huit.frama.space/remote.php/dav/calendars/Pierre/latelier-du-huit-sbastien_shared_by_admin/?export
  • Auth : session navigateur (cookies). Depuis l'extension → fetch(url, { credentials: 'include' }) + host_permissions sur https://atelier-huit.frama.space/*. Aucun mot de passe stocké.
  • Réponse : flux iCalendar brut (VCALENDAR/VEVENT).
  • Si non connecté → la requête échoue : prévoir un message "connecte-toi à Nextcloud dans un onglet".

Cas limites du flux réel (échantillon 2026-06-29, 473 VEVENT)

Réalité Chiffre Conséquence parsing
VEVENT total 473
UID uniques 381 Dédoublonner par UID (récurrences = même UID répété)
Récurrents (RRULE) 54 Gérer/ignorer les occurrences passées
Journée entière (DTSTART;VALUE=DATE) 7 Pas d'heure → le formulaire mairie attend une heure : cas à traiter
Avec LOCATION 51 / 473 La majorité n'a pas de lieu → défaut = adresse du café
Avec DESCRIPTION 142 / 473 La majorité n'a pas de description → champ souvent vide
Fuseaux Europe/Paris mais aussi Africa/Lagos Ne PAS supposer Europe/Paris : lire le vrai TZID

Recommandation parsing : ical.js (Mozilla) plutôt que regex maison — gère RRULE, TZID, VALUE=DATE.

T1 — parseur : ical.js v2.2.1 vendoré (build ESM dist/ical.js) dans extension/vendor/ical.js. ⚠️ Les VTIMEZONE embarqués dans le flux doivent être enregistrés (ICAL.TimezoneService.register) avant toJSDate(), sinon l'offset est faux pour les TZID non standards (ex. Africa/Lagos).

Écriture CalDAV — mesuré le 2026-08-13 (spike navigateur, T2)

Mesures faites depuis la console de la page d'extension, session Nextcloud ouverte. La séquence complète a été jouée, PUT no-op compris (contenu reposé à l'identique : rien modifié).

Étape Résultat mesuré
GET /csrftoken 200, corps {"token":"…=:…="} (le repli data-requesttoken n'a pas servi)
REPORT sur la collection (calendar-query filtrée sur UID) 207, en-têtes Depth: 1 + Content-Type: application/xml; charset=utf-8
PUT avec If-Match 204 → le partage est en écriture
REPORT avec un requesttoken invalide 207 quand même : l'endpoint DAV n'exige pas le jeton CSRF
  • Collection = URL du calendrier sans ?export (d'où URL_COLLECTION dérivée dans nextcloud.js).
  • Préfixes réels du multistatus : d: → DAV:, cal: → urn:ietf:params:xml:ns:caldav (plus s:, cs:, oc:, nc:). Ce sont des préfixes, pas un contrat : sélectionner par namespace (getElementsByTagNameNS), jamais par préfixe.
  • ⚠️ Le nom de la ressource n'est PAS l'UID : l'événement d'UID db2d146b-8e18-… vit dans …/00D03211-DA2E-4D06-AAAE-6E8C2355BA2B.ics. Déduire l'URL en <uid>.ics aurait échoué — d'où le REPORT préalable.
  • href du multistatus = chemin absolu depuis la racine (/remote.php/dav/…) → à résoudre contre la collection.
  • getetag est rendu avec ses guillemets ("8ee26a8f…") : If-Match le reprend verbatim.

2. Cible : formulaire mairie (Gravity Forms, form id = 6)

URL : https://www.ville-cugnaux.fr/mes-loisirs/associations/proposer-un-evenement-dans-lagenda/

Stratégie de soumission

Content script qui remplit le DOM par id, puis l'utilisateur soumet à la main.

  • Pas de params URL : Gravity Forms n'accepte ?input_X= que si "population dynamique" est activé par champ côté mairie (non).
  • Les tokens CSRF (gform_currency, state_6, version_hash) sont dans la page et gérés par le formulaire lui-même : on n'y touche pas. ⚠️ Les tokens du curl capturé sont par session, non réutilisables.

Mapping des champs (ids confirmés présents dans le HTML)

⚠️ La colonne « balise réelle » a été payée par un bug (2026-07-17). Le corps de la tâche T1 affirmait « Heures = 2 selects » : c'est faux, ce sont des <input type="number">. Le code l'a suivi et les 4 champs d'heures ont échoué (champ.options undefined → TypeError). Ne pas déduire le type d'un champ de son intitulé : le HTML est la seule source de vérité. Types ci-dessous vérifiés sur la page réelle le 2026-07-17.

id DOM name Balise réelle Contenu Source
#input_6_42 input_42 input[type=text] Organisateur config (« L'Atelier du Huit »)
#input_6_41 input_41 input[type=email] Email config
#input_6_1 input_1 input[type=text] Titre SUMMARY
#input_6_3 input_3 textarea Description DESCRIPTION
#input_6_20 input_20 select Thème mapping (voir §3)
#input_6_31 input_31 input[type=text] (datepicker) Date début jj/mm/aaaa DTSTART
#input_6_32 input_32 input[type=text] (datepicker) Date fin jj/mm/aaaa DTEND
#input_6_38_1 / #input_6_38_2 input_38[] input[type=number] (min/max, placeholder HH/MM) Heure début [HH, MM] DTSTART
#input_6_39_1 / #input_6_39_2 input_39[] input[type=number] Heure fin [HH, MM] DTEND
#input_6_35 (_1) input_35.1 input[type=checkbox] Accessibilité ⚠️ laissé intact : la machine ne sait pas si le lieu est accessible
#input_6_36 input_36 Public ciblé optionnel
#input_6_40 input_40 textarea Tarifs défaut « Gratuit »
#nova_address nova_address input[type=text] Adresse texte défaut café
#input_6_18 input_18 input[type=hidden] lat|lng|adresse défaut café
#input_6_34 input_34 input[type=file] Image ⚠️ non remplissable par script (sécurité) → manuel
#input_6_23, #input_6_43 Honeypot laisser vide

Les 4 champs d'heures acceptent le zéro-padding ("09", "00") : une suite de chiffres est un valid floating-point number au sens HTML.

Défaut café : 8 Rue du Pré Vicinal 31270 Cugnaux input_18 = 43.53753132806989|1.342981890597508|8 Rue du Pré Vicinal 31270 Cugnaux


3. Valeurs exactes du dropdown Thème (#input_6_20)

Chaînes value à utiliser telles quelles :

Culture
Atelier - Stage
Economie - Emploi
Exposition
Photographie
Rencontre
Spectacle
Enfance - Jeunesse
Jeunesse
Parentalité
Petite enfance
Scolarité
Loisirs
Mobilité
Nature - Environnement
Numérique
Participation citoyenne
Cérémonies officielles
Réunion publique
Santé
Seniors
Solidarité
Sport

Le calendrier Nextcloud n'a pas de thème → prévoir un choix par l'utilisateur dans l'UI, défaut « Culture ».


4. Vérification publication (agenda public mairie)

URL filtrée par mois : https://www.ville-cugnaux.fr/mes-loisirs/agenda/?f=1&theme=&date=periode&date_debut=MM%2FYYYY&date_fin=MM%2FYYYY&public=

Structure HTML d'un résultat (confirmée)

Chaque événement publié = <article class="card card-thumbnail card-event ..."> contenant (balise <article>, PAS <div> : vérifié sur l'agenda réel le 2026-07-17 — matcher sur la classe .card-event, agnostique de balise) :

  • Date : <time datetime="YYYY-MM-DD"> (ancre de match la plus fiable)
  • Lien direct : <a href="/agenda/<slug>/"> — parfois relatif, à résoudre contre l'agenda avant affichage ; c'est le lien à afficher dans l'extension
  • Titre : .card-title > a
  • Thème : classe event_theme-<slug>

Exemples de liens réels observés : /agenda/spectacle-jhabite-ici/, /agenda/atelier-bebe-gym/, /agenda/fete-du-14-juillet-inscription-au-repas-republicain/.

Matching Nextcloud ↔ mairie

Comparer date (<time datetime> vs DTSTART) + titre (normalisé : sans accents/emojis, ou via le slug). Tolérer les écarts mineurs.


5. Modèle de statut (rappel)

  • ignoré / soumis:AAAA-MM-JJ → tag CATEGORIES écrit en CalDAV (partagé, durable)
  • publié → dérivé de l'agenda mairie (§4), donne le lien direct
  • à faire → futur, ni ignoré, ni soumis, ni publié