# Changelog Toutes les modifications notables sont documentées ici. Format : [Keep a Changelog](https://keepachangelog.com/fr/1.0.0/) — versionnage [semver](https://semver.org/lang/fr/). --- ## [1.6.35] - 2026-05-19 ### Corrigé - `visitors.json` : utilisation de `+` au lieu de `array_merge` pour préserver les clés entières 7/14/30 (array_merge les renumérote en 0/1/2) - Admin stats / Visiteurs par pays : bouton ✕ déplacé hors du div 9rem (il était écrasé par le nom de l'AS) ; `e.stopPropagation()` ajouté pour ne pas déclencher l'accordéon - Admin stats / Visiteurs par pays : listener délégué stocké et retiré avant réajout (évite l'accumulation de handlers après chaque `renderCountry()`) ### Modifié - Graphique "Trafic total" → "Visiteurs uniques / jour" calculé depuis les IPs du top 200 (approximation) --- ## [1.6.34] - 2026-05-19 ### Ajouté - AccessLogParser : calcul des visiteurs uniques par article (IPs non-bot publiques, /post/ statut 200) sur 7 / 14 / 30 jours — stocké dans `data/UUID/visitors.json` - Page article : affichage du nombre de lecteurs (7 / 14 / 30 jours) dans la zone hero, recalculé à chaque visite de `/admin/stats` --- ## [1.6.33] - 2026-05-19 ### Ajouté - Admin stats : carte « Visiteurs uniques non-bot » en tête de page avec compteurs 7 / 14 / 30 jours (calculés sur toutes les IPs non-bot, pas seulement le top 200) - Admin stats / Visiteurs par pays : bouton « ✕ » sur chaque AS pour l'exclure des stats — les AS exclus apparaissent dans une section dédiée avec bouton « ↺ Inclure » - Admin stats / Visiteurs par pays : badge d'alerte si des IPs du top 200 n'ont pas de résolution AS - Admin stats / Visiteurs par pays : les AS exclus sont filtrés du décompte par pays et des compteurs visiteurs (soustraction approximative via le top 200) - Nouvelles actions AJAX `admin_add_excluded_as` / `admin_remove_excluded_as` (CSRF) pour gérer `data/excluded_as.json` ### Modifié - AccessLogParser : fenêtre d'analyse étendue à **30 jours** (était 14) ; calcul des visiteurs uniques par période (7 / 14 / 30 jours) sur l'ensemble des IPs non-bot - Graphiques de tendance / par article : adaptés à 30 jours (labels x toutes les 3 jours) - Articles : un seul bouton de réaction 👍 (suppression de 🔥 et 🤔) --- ## [1.6.32] - 2026-05-19 ### Modifié - Admin stats / Agents détectés : UA affiché en entier (plus de troncature à 55 car.) dans le drill-down IP et la liste agents - Admin stats / Agents détectés : bouton « + bot » sur chaque agent non classé — ajoute le UA aux patterns via AJAX sans recharger la page, déplace la ligne vers "Bots connus" - Admin stats / Agents détectés : section alimentée par `FOLIO_ALL_UAS` (tous UAs publics, bots inclus) plutôt que par agrégation depuis `ip_data` - AccessLogParser : filtrage des bots dans les compteurs pages/livres/IPs — les requêtes détectées comme bot n'alimentent plus les stats de fréquentation ; `all_uas` expose tous les UAs (bots inclus) pour la section Agents - `index.php` : chargement de `bots.json` avant la création du parser pour passer les patterns au constructeur ; `admin_add_bot` vide les caches stats après ajout ; `admin_save_bots` vide également les caches - Template : `FOLIO_ALL_UAS` et `FOLIO_CSRF` ajoutés aux variables JS de la page stats --- ## [1.6.31] - 2026-05-19 ### Ajouté - Admin stats : section « Agents détectés » en bas de page — agrège tous les user agents, détecte bots/humains, badge 🤖 pour les bots connus - Admin stats : panneau d'édition des patterns bots (un par ligne, correspondance insensible à la casse), sauvegardé dans `data/bots.json` - Admin stats / drill-down IP : section « Autres chemins » (tous chemins/statuts hors articles et livres), triée par volume - AccessLogParser : analyse tous les chemins et statuts pour les IPs publiques (pas seulement /post/ et /book/ en 200), tracking `ipAllPaths`, `ipAllDays`, `ipAgents` - `index.php` : action `admin_save_bots` — enregistre les patterns bots avec token CSRF ; initialisation automatique de `data/bots.json` avec ~50 patterns connus (Googlebot, GPTBot, curl, Scrapy…) --- ## [1.6.30] - 2026-05-19 ### Ajouté - Admin stats / drill-down IP : user agents affichés sous l'adresse IP (top 5 par fréquence, sans corrélation avec les pages) - AccessLogParser : capture du user agent (groupe 5 de la regex COMBINED), tracking `ipAgents` par IP, `ip_agents` dans le résultat --- ## [1.6.29] - 2026-05-19 ### Modifié - Admin stats / drill-down IP : chemins affichés un par ligne avec compteur entre parenthèses, triés par date de dernier accès (plus récent en premier) - AccessLogParser : suivi du dernier horodatage par chemin/IP (`ipPathTs`), `ip_top_paths` devient `{n: count, ts: timestamp}` --- ## [1.6.28] - 2026-05-19 ### Ajouté - Admin stats : drill-down AS → IPs dans l'accordéon « Visiteurs par pays » — mini sparkline 14 jours + articles/livres consultés par IP - Admin stats : `ip_data` dans le cache stats (daily + top paths par IP publique) ### Supprimé - Admin stats : section « Répartition par réseau » (fusionnée dans l'accordéon pays) --- ## [1.6.27] - 2026-05-19 ### Ajouté - Admin stats : sparklines SVG 14 jours par page dans « Pages les plus visitées » — courbe + dégradé, carte pleine largeur (#101) ### Corrigé - Admin stats : IPs privées/LAN exclues de la répartition par réseau (Uptime Kuma et hairpin NAT ne polluent plus les stats) (#102) --- ## [1.6.26] - 2026-05-16 ### Ajouté - Page publique `/books` — catalogue de tous les livres avec ≥ 1 article publié, cards cover/titre/description/nombre de pages (#99) - Accueil : section « Livres » (max 6) après les redécouvertes avec lien « Voir tous → /books » (#100) --- ## [1.6.25] - 2026-05-16 ### Ajouté - Admin : onglet « IA » — statut provider/clé, sélecteur `anthropic`/`claude_code`, champ modèle, procédure d'installation CLI, sauvegarde dans `site_settings.json` (#97) - `AiService` : support du provider Claude Code CLI via `proc_open` + lecture provider/modèle depuis `SiteSettings` (#97) - Éditeur : bouton IA unique « Analyser et proposer » — un seul appel retourne l'analyse critique et la réécriture via séparateur `===CRITIQUE===/===REWRITE===` (#96) ### Corrigé - Éditeur IA : boutons placés dans `wizard/step1.php` (la vraie page d'édition) ; `ai-editor.js` adapté pour `#wz-content` et extraction du titre depuis le Markdown (#96) - Sécurité CSP : extraction du `