Files
dokuwiki-plugin-botmon/script.js
2025-08-29 23:14:10 +03:00

233 lines
5.9 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* DokuWiki Monitor Plugin Script file */
/* 29.08.2025 - 1.0.5 - initial release */
/* Authors: Sascha Leib <ad@hominem.info> */
const Monitor = {
init: function() {
//console.info('Monitor.init()');
// find the plugin basedir:
this._baseDir = document.currentScript.src.substring(0, document.currentScript.src.indexOf('/exe/'))
+ '/plugins/monitor/';
// read the page language from the DOM:
this._lang = document.getRootNode().documentElement.lang || this._lang;
// get the time offset:
this._timeDiff = Monitor.t._getTimeOffset();
// init the sub-objects:
Monitor.t._callInit(this);
},
_baseDir: null,
_lang: 'en',
_today: (new Date()).toISOString().slice(0, 10),
_timeDiff: '',
/* internal tools */
t: {
/* helper function to call inits of sub-objects */
_callInit: function(obj) {
//console.info('Monitor.t._callInit(obj=',obj,')');
/* call init / _init on each sub-object: */
Object.keys(obj).forEach( (key,i) => {
const sub = obj[key];
let init = null;
if (typeof sub === 'object' && sub.init) {
init = sub.init;
}
// bind to object
if (typeof init == 'function') {
const init2 = init.bind(sub);
init2(obj);
}
});
},
/* helper function to calculate the time difference to UTC: */
_getTimeOffset: function() {
const now = new Date();
let offset = now.getTimezoneOffset(); // in minutes
const sign = Math.sign(offset); // +1 or -1
offset = Math.abs(offset); // always positive
let hours = 0;
while (offset >= 60) {
hours += 1;
offset -= 60;
}
return ( hours > 0 ? sign * hours + 'h' : '') + (offset > 0 ? ` ${offset}min` : '');
}
}
}
/* everything specific to the "Today" tab is self-contained here: */
Monitor.today = {
init: function() {
//console.info('Monitor.today.init()');
// set the title:
const tDiff = (Monitor._timeDiff != '' ? ` (${Monitor._timeDiff})` : ' (<abbr>UTC</abbr>)' );
Monitor.today.status.setTitle(`Showing visits for <time datetime=${Monitor._today}>${Monitor._today}</time>${tDiff}`);
// init sub-objects:
Monitor.t._callInit(this);
},
data: {
init: function() {
//console.info('Monitor.today.data.init()');
// call sub-inits:
Monitor.t._callInit(this);
// load the first log file:
Monitor.today.data.loadLogFile('srv');
},
bots: {
// loads the list of known bots from a JSON file:
init: async function() {
//console.info('Monitor.today.data.bots.init()');
// Load the list of known bots:
Monitor.today.status.showBusy("Loading known bots&nbsp;&hellip;");
const url = Monitor._baseDir + 'data/known-bots.json';
console.log(url);
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`${response.status} ${response.statusText}`);
}
Monitor.today.data.bots._list = await response.json();
Monitor.today.data.bots._ready = true;
// TODO: allow using the bots list...
} catch (error) {
Monitor.today.status.setError("Error while loading the known bots file: " + error.message);
} finally {
Monitor.today.status.hideBusy("Done.");
}
},
// returns bot info if the clientId matches a known bot, null otherwise:
match: function(clientId) {
// TODO!
},
// indicates if the list is loaded and ready to use:
_ready: false,
// the actual bot list is stored here:
_list: []
},
loadLogFile: async function(type) {
console.info('Monitor.today.data.loadLogFile(',type,')');
let typeName = '';
let columns = [];
switch (type) {
case "srv":
typeName = "Server";
columns = ['ts','ip','pg','id','usr','client'];
break;
break;
case "log":
typeName = "Page load";
columns = ['ts','ip','pg','id','usr'];
break;
case "tck":
typeName = "Ticker";
columns = ['ts','ip','pg','id'];
break;
default:
console.warn(`Unknown log type ${type}.`);
return;
}
// Load the list of known bots:
Monitor.today.status.showBusy(`Loading ${typeName} log file &nbsp;&hellip;`);
const url = Monitor._baseDir + `logs/${Monitor._today}.${type}`;
console.log("Loading:",url);
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`${response.status} ${response.statusText}`);
}
const events = await response.text();
console.log(events);
//Monitor.today.data.serverEvents._ready = true;
// TODO: parse the file...
} catch (error) {
Monitor.today.status.setError(`Error while loading the ${typeName} log file: ${error.message}.`);
} finally {
Monitor.today.status.hideBusy("Done.");
}
}
},
status: {
setText: function(txt) {
const el = document.getElementById('monitor__today__status');
if (el && Monitor.today.status._errorCount <= 0) {
el.innerText = txt;
}
},
setTitle: function(html) {
const el = document.getElementById('monitor__today__title');
if (el) {
el.innerHTML = html;
}
},
setError: function(txt) {
console.error(txt);
Monitor.today.status._errorCount += 1;
const el = document.getElementById('monitor__today__status');
if (el) {
el.innerText = "An error occured. See the browser log for details!";
el.classList.add('error');
}
},
_errorCount: 0,
showBusy: function(txt = null) {
Monitor.today.status._busyCount += 1;
const el = document.getElementById('monitor__today__busy');
if (el) {
el.style.display = 'inline-block';
}
if (txt) Monitor.today.status.setText(txt);
},
_busyCount: 0,
hideBusy: function(txt = null) {
const el = document.getElementById('monitor__today__busy');
Monitor.today.status._busyCount -= 1;
if (Monitor.today.status._busyCount <= 0) {
if (el) el.style.display = 'none';
if (txt) Monitor.today.status.setText(txt);
}
}
}
}
/* check if the nustat admin panel is open: */
if (document.getElementById('monitor__admin')) {
Monitor.init();
}