From 9e932cfc9db0da0e490a32ddf8467a543aaa7d01 Mon Sep 17 00:00:00 2001 From: Sascha Leib Date: Tue, 16 Sep 2025 23:08:54 +0200 Subject: [PATCH] Refactoring and cleanup --- admin.php | 4 +- img/bounce.svg | 57 +-------- img/info.svg | 2 +- img/more.svg | 1 + img/page.svg | 2 +- img/referers.png | Bin 8495 -> 10643 bytes plugin.info.txt | 2 +- script.js | 316 +++++++++++++++++++++++++---------------------- style.less | 6 + 9 files changed, 178 insertions(+), 212 deletions(-) create mode 100644 img/more.svg diff --git a/admin.php b/admin.php index edfef34..6e1b3e1 100644 --- a/admin.php +++ b/admin.php @@ -55,7 +55,7 @@ class admin_plugin_botmon extends AdminPlugin {
Loading …
- Bot overview (page views) + Overview
@@ -63,7 +63,7 @@ class admin_plugin_botmon extends AdminPlugin {
- Web metrics + Web metrics (humans only)
diff --git a/img/bounce.svg b/img/bounce.svg index 1f4d43a..7a8e919 100644 --- a/img/bounce.svg +++ b/img/bounce.svg @@ -1,56 +1 @@ - - - - - arrow-down-left - - - - arrow-down-left - - - - - - + \ No newline at end of file diff --git a/img/info.svg b/img/info.svg index f1daa8f..afd15a4 100644 --- a/img/info.svg +++ b/img/info.svg @@ -1 +1 @@ -information \ No newline at end of file +information \ No newline at end of file diff --git a/img/more.svg b/img/more.svg new file mode 100644 index 0000000..861d365 --- /dev/null +++ b/img/more.svg @@ -0,0 +1 @@ +Others \ No newline at end of file diff --git a/img/page.svg b/img/page.svg index 91f925b..a92a815 100644 --- a/img/page.svg +++ b/img/page.svg @@ -1 +1 @@ -page \ No newline at end of file +page \ No newline at end of file diff --git a/img/referers.png b/img/referers.png index 2fed645bb418edd614a85bec314f29b459919521..ff68e5bee3fa1d9032f44955617aa7343887d32c 100644 GIT binary patch delta 10468 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 diff --git a/plugin.info.txt b/plugin.info.txt index 34ccea7..ec31480 100644 --- a/plugin.info.txt +++ b/plugin.info.txt @@ -1,7 +1,7 @@ base botmon author Sascha Leib email ad@hominem.com -date 2025-09-15 +date 2025-09-16 name Bot Monitoring desc A tool for monitoring and analysing bot traffic to your wiki (under development) url https://www.dokuwiki.org/plugin:botmon diff --git a/script.js b/script.js index 39cd5fa..4b162af 100644 --- a/script.js +++ b/script.js @@ -578,9 +578,55 @@ BotMon.live = { BotMon.live.gui.status.hideBusy('Done.'); }, + // get a list of known bots: + getTopBots: function(max) { + //console.info('BotMon.live.data.analytics.getTopBots('+max+')'); + + //console.log(BotMon.live.data.analytics.groups.knownBots); + + let botsList = BotMon.live.data.analytics.groups.knownBots.toSorted( (a, b) => { + return b._pageViews.length - a._pageViews.length; + }); + + const other = { + 'id': 'other', + 'name': "Others", + 'count': 0 + }; + + const rList = []; + const max2 = ( botsList.length > max ? max-1 : botsList.length ); + let total = 0; // adding up the items + for (let i=0; i max2) { + rList.push(other); + }; + + rList.forEach( it => { + it.pct = (it.count * 100 / total); + }); + + return rList; + }, + // Referer List: - _refererList: [], - _refererListCount: 0, + _refererList: [], addToRefererList: function(ref) { //console.log('BotMon.live.data.analytics.addToRefererList',ref); @@ -592,18 +638,12 @@ BotMon.live = { return; } - // find the referer ID: - let refId = 'null'; - if (ref && ref.host) { - const hArr = ref.host.split('.'); - const tld = hArr[hArr.length-1]; - refId = ( tld == 'localhost' ? tld : hArr[hArr.length-2] + ( tld.length > 3 ? '.' + tld : '' ) ); - } + const refInfo = me.getRefererInfo(ref); // already exists? let refObj = null; for (let i = 0; i < me._refererList.length; i++) { - if (me._refererList[i].id == refId) { + if (me._refererList[i].id == refInfo.id) { refObj = me._refererList[i]; break; } @@ -611,16 +651,31 @@ BotMon.live = { // if not exists, create it: if (!refObj) { - refObj = { - id: refId, - count: 0 - }; + refObj = refInfo; + refObj.count = 1; me._refererList.push(refObj); } else { refObj.count += 1; } - // add to total count: - me._refererListCount += 1; + }, + + getRefererInfo: function(url) { + //console.log('BotMon.live.data.analytics.getRefererInfo',url); + + // find the referer ID: + let refId = 'null'; + let refName = 'No Referer'; + if (url && url.host) { + const hArr = url.host.split('.'); + const tld = hArr[hArr.length-1]; + refId = ( tld == 'localhost' ? tld : hArr[hArr.length-2] + ( tld.length > 3 ? '.' + tld : '' ) ); + refName = hArr[hArr.length-2] + '.' + tld; + } + + return { + 'id': refId, + 'n': refName + }; }, getTopReferers: function(max) { @@ -628,24 +683,53 @@ BotMon.live = { const me = BotMon.live.data.analytics; - const rList = []; // return array + return me._makeTopList(me._refererList, max); + }, + + _makeTopList: function(arr, max) { + //console.info(('BotMon.live.data.analytics._makeTopList(arr,' + max + ')')); + + const me = BotMon.live.data.analytics; // sort the list: - me._refererList.sort( (a,b) => { + arr.sort( (a,b) => { return b.count - a.count; }); - // get the top: - for (let i = 0; i < max; i++) { - const it = me._refererList[i]; - const rIt = { - id: it.id, - count: it.count, - pct: (it.count / me._refererListCount * 100).toFixed(0) - }; - rList.push(rIt); + const rList = []; // return array + const max2 = ( arr.length >= max ? max-1 : arr.length ); + const other = { + 'id': 'other', + 'name': "Others", + 'count': 0 + }; + let total = 0; // adding up the items + for (let i=0; Math.min(max, arr.length) > i; i++) { + const it = arr[i]; + if (it) { + if (i < max2) { + const rIt = { + id: it.id, + name: (it.n ? it.n : it.id), + count: it.count + }; + rList.push(rIt); + } else { + other.count += it.count; + } + total += it.count; + } } - + + // add the "other" item, if needed: + if (arr.length > max2) { + rList.push(other); + }; + + rList.forEach( it => { + it.pct = (it.count * 100 / total); + }); + return rList; }, @@ -687,11 +771,11 @@ BotMon.live = { } if (arr) { - let cRec = arr.find( it => it.iso == iso); + let cRec = arr.find( it => it.id == iso); if (!cRec) { cRec = { - 'iso': iso, - 'name': name, + 'id': iso, + 'n': name, 'count': 1 }; arr.push(cRec); @@ -730,25 +814,10 @@ BotMon.live = { break; default: console.warn(`Unknown user type ${type} in function getCountryList.`); + return; } - if (arr) { - // sort by visit count: - arr.sort( (a,b) => b.count - a.count); - - // reduce to only the top (max) items and create the target format: - let rList = []; - for (let i=0; Math.min(max, arr.length) > i; i++) { - const cRec = arr[i]; - rList.push({ - 'iso': cRec.iso, - 'name': cRec.name, - 'count': cRec.count - }); - } - return rList; - } - return []; + return me._makeTopList(arr, max); }, /* browser and platform of human visitors */ @@ -766,8 +835,9 @@ BotMon.live = { let bRec = me._browsers.find( it => it.id == browserRec.id); if (!bRec) { bRec = { - 'id': browserRec.id, - 'count': 1 + id: browserRec.id, + n: browserRec.n, + count: 1 }; me._browsers.push(bRec); } else { @@ -781,8 +851,9 @@ BotMon.live = { let pRec = me._platforms.find( it => it.id == platformRec.id); if (!pRec) { pRec = { - 'id': platformRec.id, - 'count': 1 + id: platformRec.id, + n: platformRec.n, + count: 1 }; me._platforms.push(pRec); } else { @@ -795,84 +866,15 @@ BotMon.live = { getTopBrowsers: function(max) { const me = BotMon.live.data.analytics; - - me._browsers.sort( (a,b) => b.count - a.count); - // how many browsers to show: - const max2 = ( me._browsers.length >= max ? max-1 : max ); - - const rArr = []; // return array - let total = 0; - const others = { - 'id': 'other', - 'name': "Others", - 'count': 0 - }; - for (let i=0; i < me._browsers.length; i++) { - if (i < max2) { - rArr.push({ - 'id': me._browsers[i].id, - 'name': BotMon.live.data.clients.getName(me._browsers[i].id), - 'count': me._browsers[i].count - }); - total += me._browsers[i].count; - } else { - others.count += me._browsers[i].count; - total += me._browsers[i].count; - } - }; - - if (me._browsers.length > (max-1)) { - rArr.push(others); - }; - - // update percentages: - rArr.forEach( it => { - it.pct = Math.round(it.count * 100 / total); - }); - - return rArr; + return me._makeTopList(me._browsers, max); }, getTopPlatforms: function(max) { const me = BotMon.live.data.analytics; - - me._platforms.sort( (a,b) => b.count - a.count); - // how many browsers to show: - const max2 = ( me._platforms.length >= max ? max-1 : max ); - const rArr = []; // return array - let total = 0; - const others = { - 'id': 'other', - 'name': "Others", - 'count': 0 - }; - for (let i=0; i < me._platforms.length; i++) { - if (i < max2) { - rArr.push({ - 'id': me._platforms[i].id, - 'name': BotMon.live.data.platforms.getName(me._platforms[i].id), - 'count': me._platforms[i].count - }); - total += me._platforms[i].count; - } else { - others.count += me._platforms[i].count; - total += me._platforms[i].count; - } - }; - - if (me._platforms.length > (max-1)) { - rArr.push(others); - }; - - // update percentages: - rArr.forEach( it => { - it.pct = Math.round(it.count * 100 / total); - }); - - return rArr; + return me._makeTopList(me._platforms, max); } }, @@ -1490,14 +1492,16 @@ BotMon.live = { const data = BotMon.live.data.analytics.data; + const maxItemsPerList = 5; // how many list items to show? + // shortcut for neater code: const makeElement = BotMon.t._makeElement; const botsVsHumans = document.getElementById('botmon__today__botsvshumans'); if (botsVsHumans) { - botsVsHumans.appendChild(makeElement('dt', {}, "Bots vs. Humans")); + botsVsHumans.appendChild(makeElement('dt', {}, "Page views by category:")); - for (let i = 3; i >= 0; i--) { + for (let i = 0; i <= 4; i++) { const dd = makeElement('dd'); let title = ''; let value = ''; @@ -1518,6 +1522,10 @@ BotMon.live = { title = "Known bots:"; value = data.bots.known; break; + case 4: + title = "Total:"; + value = data.totalPageViews; + break; default: console.warn(`Unknown list type ${i}.`); } @@ -1528,20 +1536,20 @@ BotMon.live = { } // update known bots list: - const botlist = document.getElementById('botmon__botslist'); /* Known bots */ - botlist.innerHTML = "
Known bots (top 5)
"; + const botElement = document.getElementById('botmon__botslist'); /* Known bots */ + if (botElement) { + botElement.innerHTML = `
Known bots (top ${maxItemsPerList})
`; - let bots = BotMon.live.data.analytics.groups.knownBots.toSorted( (a, b) => { - return b._pageViews.length - a._pageViews.length; - }); - - for (let i=0; i < Math.min(bots.length, 5); i++) { - const dd = makeElement('dd'); - dd.appendChild(makeElement('span', {'class': 'has_icon bot bot_' + bots[i]._bot.id }, bots[i]._bot.n)); - dd.appendChild(makeElement('span', undefined, bots[i]._pageViews.length)); - botlist.appendChild(dd); + let botList = BotMon.live.data.analytics.getTopBots(maxItemsPerList); + botList.forEach( (botInfo) => { + const bli = makeElement('dd'); + bli.appendChild(makeElement('span', {'class': 'has_icon bot bot_' + botInfo.id }, botInfo.name)); + bli.appendChild(makeElement('span', {'class': 'count' }, botInfo.count)); + botElement.append(bli) + }); } + // update the suspected bot IP ranges list: /*const botIps = document.getElementById('botmon__today__botips'); if (botIps) { @@ -1559,11 +1567,11 @@ BotMon.live = { // update the top bot countries list: const botCountries = document.getElementById('botmon__today__countries'); if (botCountries) { - botCountries.appendChild(makeElement('dt', {}, "Bot Countries (top 5)")); + botCountries.appendChild(makeElement('dt', {}, `Bot Countries (top ${maxItemsPerList})`)); const countryList = BotMon.live.data.analytics.getCountryList('likely_bot', 5); countryList.forEach( (cInfo) => { const cLi = makeElement('dd'); - cLi.appendChild(makeElement('span', {'class': 'has_icon country ctry_' + cInfo.iso.toLowerCase() }, cInfo.name)); + cLi.appendChild(makeElement('span', {'class': 'has_icon country ctry_' + cInfo.id.toLowerCase() }, cInfo.name)); cLi.appendChild(makeElement('span', {'class': 'count' }, cInfo.count)); botCountries.appendChild(cLi); }); @@ -1605,9 +1613,9 @@ BotMon.live = { const wmclients = document.getElementById('botmon__today__wm_clients'); if (wmclients) { - wmclients.appendChild(makeElement('dt', {}, "Top browsers")); + wmclients.appendChild(makeElement('dt', {}, "Browsers")); - const clientList = BotMon.live.data.analytics.getTopBrowsers(5); + const clientList = BotMon.live.data.analytics.getTopBrowsers(maxItemsPerList); if (clientList) { clientList.forEach( (cInfo) => { const cDd = makeElement('dd'); @@ -1615,7 +1623,7 @@ BotMon.live = { cDd.appendChild(makeElement('span', { 'class': 'count', 'title': cInfo.count + " page views" - }, Math.round(cInfo.pct) + '%')); + }, cInfo.pct.toFixed(1) + '%')); wmclients.appendChild(cDd); }); } @@ -1625,9 +1633,9 @@ BotMon.live = { const wmplatforms = document.getElementById('botmon__today__wm_platforms'); if (wmplatforms) { - wmplatforms.appendChild(makeElement('dt', {}, "Top platforms")); + wmplatforms.appendChild(makeElement('dt', {}, "Platforms")); - const pfList = BotMon.live.data.analytics.getTopPlatforms(5); + const pfList = BotMon.live.data.analytics.getTopPlatforms(maxItemsPerList); if (pfList) { pfList.forEach( (pInfo) => { const pDd = makeElement('dd'); @@ -1635,7 +1643,7 @@ BotMon.live = { pDd.appendChild(makeElement('span', { 'class': 'count', 'title': pInfo.count + " page views" - }, Math.round(pInfo.pct) + '%')); + }, pInfo.pct.toFixed(1) + '%')); wmplatforms.appendChild(pDd); }); } @@ -1645,17 +1653,17 @@ BotMon.live = { const wmreferers = document.getElementById('botmon__today__wm_referers'); if (wmreferers) { - wmreferers.appendChild(makeElement('dt', {}, "Top Referers")); + wmreferers.appendChild(makeElement('dt', {}, "Referers")); - const refList = BotMon.live.data.analytics.getTopReferers(5); + const refList = BotMon.live.data.analytics.getTopReferers(maxItemsPerList); if (refList) { refList.forEach( (rInfo) => { const rDd = makeElement('dd'); - rDd.appendChild(makeElement('span', {'class': 'has_icon referer ref_' + rInfo.id }, rInfo.id)); + rDd.appendChild(makeElement('span', {'class': 'has_icon referer ref_' + rInfo.id }, rInfo.name)); rDd.appendChild(makeElement('span', { 'class': 'count', 'title': rInfo.count + " references" - }, Math.round(rInfo.pct) + '%')); + }, rInfo.pct.toFixed(1) + '%')); wmreferers.appendChild(rDd); }); } @@ -1859,6 +1867,15 @@ BotMon.live = { }, ( data._country || "Unknown") )); } + // referer icons: + if ((data._type == BM_USERTYPE.HUMAN || data._type == BM_USERTYPE.LIKELY_BOT) && data.ref) { + const refInfo = BotMon.live.data.analytics.getRefererInfo(new URL(data.ref)); + span1.appendChild(make('span', { + 'class': 'icon_only referer ref_' + refInfo.id, + 'title': "Referer: " + data.ref + }, refInfo.n)); + } + summary.appendChild(span1); const span2 = make('span'); /* right-hand group */ @@ -1965,9 +1982,6 @@ BotMon.live = { }, data._country + ' (' + data.geo + ')')); } - /*dl.appendChild(make('dt', {}, "Visitor Type:")); - dl.appendChild(make('dd', undefined, data._type ));*/ - dl.appendChild(make('dt', {}, "Session ID:")); dl.appendChild(make('dd', {'class': 'has_icon session typ_' + data.typ}, data.id)); diff --git a/style.less b/style.less index a112e57..55a86e5 100644 --- a/style.less +++ b/style.less @@ -51,6 +51,7 @@ &.bot_claude::before { background-position-y: -160px } &.bot_applemsgs::before { background-position-y: -180px } &.bot_reddit::before { background-position-y: -200px } + &.bot_other::before { background-image: url('img/more.svg') } /* platform icons */ &.platform::before { background-image: url('img/platforms.png') } @@ -68,6 +69,7 @@ &.pf_hmos::before { background-position-y: -220px } &.pf_tizen::before { background-position-y: -240px } &.pf_fire::before { background-position-y: -260px } + &.pf_other::before { background-image: url('img/more.svg') } /* browser icons */ &.client::before { background-image: url('img/clients.png') } @@ -89,6 +91,7 @@ &.cl_chromeold::before { background-position-y: -320px } &.cl_ecosia::before { background-position-y: -340px } &.cl_webkit::before { background-position-y: -360px } + &.cl_other::before { background-image: url('img/more.svg') } /* Country flags */ /* Note: flag images and CSS adapted from: https://github.com/lafeber/world-flags-sprite/ */ @@ -353,6 +356,9 @@ &.ref_duckduckgo::before { background-position-y: -120px } &.ref_ecosia::before { background-position-y: -140px } &.ref_yandex::before { background-position-y: -160px } + &.ref_chatgpt::before { background-position-y: -180px } + &.ref_brave::before { background-position-y: -200px } + &.ref_other::before { background-image: url('img/more.svg') } } /* grid layout for the overview: */