diff --git a/README.md b/README.md index 83f450e..27d864f 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ -# dokuwiki-plugin-monitor +# DokuWiki Monitoring Plugin Plugin for live-monitoring your DokuWiki instance + +#TODO: Work in progress \ No newline at end of file diff --git a/action.php b/action.php new file mode 100644 index 0000000..d12e69b --- /dev/null +++ b/action.php @@ -0,0 +1,56 @@ + + */ + +class action_plugin_monitor extends DokuWiki_Action_Plugin { + + /** + * Registers a callback functions + * + * @param EventHandler $controller DokuWiki's event controller object + * @return void + */ + public function register(EventHandler $controller) { + $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'insertHeader'); + } + + /** + * Inserts tracking code to the page header + * + * @param Event $event event object by reference + * @return void + */ + public function insertHeader(Event $event, $param) { + + global $INFO; + + // is there a user logged in? + $username = ( !empty($INFO['userinfo']) && !empty($INFO['userinfo']['name']) + ? $INFO['userinfo']['name'] : null); + + // build the tracker code: + $code = NL . DOKU_TAB . "document._monitor = {'t0': Date.now()};" . NL; + if ($username) { + $code .= DOKU_TAB . 'document._monitor.user = "' . $username . '";'. NL; + } + $code .= DOKU_TAB . "addEventListener('load',function(){" . NL; + + $code .= DOKU_TAB . DOKU_TAB . "const e=document.createElement('script');" . NL; + $code .= DOKU_TAB . DOKU_TAB . "e.async=true;e.defer=true;" . NL; + $code .= DOKU_TAB . DOKU_TAB . "e.src='".DOKU_BASE."lib/plugins/monitor/client.js';" . NL; + $code .= DOKU_TAB . DOKU_TAB . "document.getElementsByTagName('head')[0].appendChild(e);" . NL; + $code .= DOKU_TAB . "});" . NL; + + $event->data['script'][] = [ + '_data' => $code + ]; + } +} \ No newline at end of file diff --git a/client.js b/client.js new file mode 100644 index 0000000..0cfd11b --- /dev/null +++ b/client.js @@ -0,0 +1,75 @@ +monitor_client = { + init: function() { + + /* send the page view request: */ + this._onPageView(this._src.replace( this._scriptName, '/view.php')); + + /* send the first heartbeat signal after x seconds: */ + setTimeout(this._onHeartbeat.bind(this, this._src.replace( this._scriptName, '/tock.php')),this._heartbeat * 1000); + }, + + /* keep a reference to the script URL: */ + _src: document.currentScript.src, + + /* heartbeat signal every x seconds: */ + _heartbeat: 30, + + /* name of this script (with slash): */ + _scriptName: '/client.js', + + /* function to init page data on server: */ + _onPageView: async function(url) { + try { + + /* collect the data to send: */ + const visit = { + 'pg': JSINFO.id, + 'u': document._monitor.user || null, + 'lg': navigator.language, + 'tz': new Date().getTimezoneOffset() /*, + 'url': window.location.href, + 'r': document.referrer, + 'lt': ( document._monitor ? Date.now() - document._monitor.t0 : null), + 'scr': screen.width+':'+screen.height, + 'l': navigator.languages */ + } + + /* compile to a FormData object: */ + const data = new FormData(); + data.append( "visit", JSON.stringify( visit ) ); + + /* send the request */ + const response = await fetch(url + '?t=' + Date.now(), { + method: 'POST', + body: data + }); + if (!response.ok) { + throw new Error(response.status + ' ' + response.statusText + ' - ' + url); + } + } catch (err) { + console.error('Error: ', err); + } + }, + + /* function to call regularly to show the user is still on the page: */ + _onHeartbeat: async function(url) { + console.info('monitor_client._onHeartbeat', url); + console.log(this); + try { + const response = await fetch(url + '?p=' + encodeURIComponent(JSINFO.id) + '&t=' + Date.now(), { + method: 'HEAD', + }); + if (!response.ok) { + throw new Error(response.status + ' ' + response.statusText + ' - ' + url); + } + } catch (err) { + console.error(err); + } finally { + /* send the next heartbeat signal after x seconds: */ + setTimeout(this._onHeartbeat.bind(this, this._src.replace( this._scriptName, '/tock.php')),this._heartbeat * 1000); + } + } +} + +// init the script: +monitor_client.init(); \ No newline at end of file diff --git a/plugin.info.txt b/plugin.info.txt new file mode 100644 index 0000000..c45079a --- /dev/null +++ b/plugin.info.txt @@ -0,0 +1,7 @@ +base monitor +author Sascha Leib +email ad@hominem.com +date 2025-08-20 +name Monitoring +desc Live monitoring traffic on your DokuWiki instance (under development) +url https://www.dokuwiki.org/plugin:nustats