v1.6.32 : UA en entier + bouton « + bot » + filtrage bots des stats
- Agents détectés : UA affiché sans troncature (drill-down et liste) - Bouton « + bot » pour ajouter un agent aux patterns via AJAX (CSRF) - Section Agents alimentée par all_uas (tous UAs publics, bots inclus) - AccessLogParser : bots exclus des compteurs pages/livres/visiteurs - Caches stats vidés après chaque modification des patterns Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -103,11 +103,11 @@ function botBadge(ua) {
|
||||
var ips = ipsByAsn[asnKey] || [];
|
||||
|
||||
var ipRows = ips.slice(0, 20).map(function (ipInfo) {
|
||||
// Agents sous l'IP avec badge bot
|
||||
// Agents sous l'IP avec badge bot (UA en entier)
|
||||
var agentsHtml = '';
|
||||
(ipInfo.agents || []).forEach(function (ua) {
|
||||
agentsHtml += '<div style="font-size:.65rem;color:#adb5bd;line-height:1.4;word-break:break-all">'
|
||||
+ botBadge(ua) + esc(trunc(ua, 55)) + '</div>';
|
||||
+ botBadge(ua) + esc(ua) + '</div>';
|
||||
});
|
||||
|
||||
// Chemins triés : /post/ et /book/ avec ts, reste sans ts
|
||||
@@ -211,23 +211,15 @@ function botBadge(ua) {
|
||||
|
||||
// ── Liste consolidée de tous les agents ──────────────────────────────────────
|
||||
(function () {
|
||||
var el = document.getElementById('stats-agents-container');
|
||||
var badge = document.getElementById('agents-count');
|
||||
var ipData = (typeof FOLIO_IP_DATA !== 'undefined') ? FOLIO_IP_DATA : {};
|
||||
var el = document.getElementById('stats-agents-container');
|
||||
var badge = document.getElementById('agents-count');
|
||||
var allUas = (typeof FOLIO_ALL_UAS !== 'undefined') ? FOLIO_ALL_UAS : {};
|
||||
var csrf = (typeof FOLIO_CSRF !== 'undefined') ? FOLIO_CSRF : '';
|
||||
if (!el) { return; }
|
||||
|
||||
// Agréger toutes les UAs depuis FOLIO_IP_DATA
|
||||
var uaCounts = {};
|
||||
Object.keys(ipData).forEach(function (ip) {
|
||||
(ipData[ip].agents || []).forEach(function (ua) {
|
||||
uaCounts[ua] = (uaCounts[ua] || 0) + (ipData[ip].hits || 0);
|
||||
});
|
||||
});
|
||||
|
||||
var agents = Object.keys(uaCounts).map(function (ua) {
|
||||
return { ua: ua, hits: uaCounts[ua], bot: isBot(ua) };
|
||||
var agents = Object.keys(allUas).map(function (ua) {
|
||||
return { ua: ua, hits: allUas[ua], bot: isBot(ua) };
|
||||
}).sort(function (a, b) {
|
||||
// Bots d'abord, puis par hits desc
|
||||
if (a.bot !== b.bot) { return a.bot ? -1 : 1; }
|
||||
return b.hits - a.hits;
|
||||
});
|
||||
@@ -239,14 +231,38 @@ function botBadge(ua) {
|
||||
|
||||
var bots = agents.filter(function (a) { return a.bot; });
|
||||
var unknown = agents.filter(function (a) { return !a.bot; });
|
||||
if (badge) { badge.textContent = '— ' + bots.length + ' bot(s) détecté(s) sur ' + agents.length; }
|
||||
if (badge) { badge.textContent = '— ' + bots.length + ' bot(s) sur ' + agents.length; }
|
||||
|
||||
function addBot(ua, btn) {
|
||||
btn.disabled = true;
|
||||
var fd = new FormData();
|
||||
fd.append('_csrf', csrf);
|
||||
fd.append('pattern', ua);
|
||||
fetch('/?action=admin_add_bot', { method: 'POST', body: fd })
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (d) {
|
||||
if (d.ok) {
|
||||
_botPatterns.push(ua);
|
||||
btn.closest('tr').querySelector('td:first-child').innerHTML = '<span title="Bot">🤖</span>';
|
||||
btn.remove();
|
||||
} else {
|
||||
btn.disabled = false;
|
||||
}
|
||||
})
|
||||
.catch(function () { btn.disabled = false; });
|
||||
}
|
||||
|
||||
function agentRow(a) {
|
||||
var addBtn = (!a.bot)
|
||||
? '<button class="btn btn-outline-secondary btn-sm py-0 px-1 ms-2 add-bot-btn"'
|
||||
+ ' style="font-size:.65rem;white-space:nowrap" title="Ajouter aux bots">+ bot</button>'
|
||||
: '';
|
||||
return '<tr>'
|
||||
+ '<td class="ps-3" style="width:1.5rem;vertical-align:top;padding-top:6px">'
|
||||
+ (a.bot ? '<span title="Bot">🤖</span>' : '<span class="text-muted" title="Inconnu">?</span>') + '</td>'
|
||||
+ '<td style="word-break:break-all;vertical-align:top">'
|
||||
+ '<code style="font-size:.72rem">' + esc(a.ua) + '</code></td>'
|
||||
+ '<code style="font-size:.72rem">' + esc(a.ua) + '</code>'
|
||||
+ addBtn + '</td>'
|
||||
+ '<td class="text-end text-muted small pe-3" style="width:5rem;vertical-align:top;white-space:nowrap">'
|
||||
+ a.hits.toLocaleString('fr-FR') + '</td>'
|
||||
+ '</tr>';
|
||||
@@ -277,6 +293,15 @@ function botBadge(ua) {
|
||||
|
||||
html += '</tbody></table></div>';
|
||||
el.innerHTML = html;
|
||||
|
||||
// Délégation : boutons "+ bot"
|
||||
el.addEventListener('click', function (e) {
|
||||
var btn = e.target.closest('.add-bot-btn');
|
||||
if (!btn) { return; }
|
||||
var row = btn.closest('tr');
|
||||
var code = row ? row.querySelector('code') : null;
|
||||
if (code) { addBot(code.textContent, btn); }
|
||||
});
|
||||
}());
|
||||
|
||||
// ── Pages les plus visitées (RSS XML + sparklines) ───────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user