UI improvements
And also style changes
This commit is contained in:
124
action.php
124
action.php
@@ -23,17 +23,23 @@ class action_plugin_botmon extends DokuWiki_Action_Plugin {
|
||||
|
||||
global $ACT;
|
||||
|
||||
// initialize the session id and type with random data:
|
||||
$this->sessionId = rand(1000000, 9999999);
|
||||
$this->sessionType = 'rnd';
|
||||
|
||||
// insert header data into the page:
|
||||
if ($ACT == 'show') {
|
||||
if ($ACT == 'show' || $ACT == 'edit' || $ACT == 'media') {
|
||||
$controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'insertHeader');
|
||||
|
||||
// Override the page rendering, if a captcha needs to be displayed:
|
||||
$controller->register_hook('TPL_ACT_RENDER', 'BEFORE', $this, 'showCaptcha');
|
||||
|
||||
} else if ($ACT == 'admin' && isset($_REQUEST['page']) && $_REQUEST['page'] == 'botmon') {
|
||||
$controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'insertAdminHeader');
|
||||
}
|
||||
|
||||
// Override the page rendering, if a captcha needs to be displayed:
|
||||
if ($ACT !== 'admin') {
|
||||
$controller->register_hook('TPL_ACT_RENDER', 'BEFORE', $this, 'showCaptcha');
|
||||
}
|
||||
}
|
||||
|
||||
// also show a captcha before the image preview
|
||||
$controller->register_hook('TPL_IMG_DISPLAY', 'BEFORE', $this, 'showImageCaptcha');
|
||||
|
||||
// write to the log after the page content was displayed:
|
||||
$controller->register_hook('TPL_CONTENT_DISPLAY', 'AFTER', $this, 'writeServerLog');
|
||||
@@ -59,14 +65,8 @@ class action_plugin_botmon extends DokuWiki_Action_Plugin {
|
||||
// populate the session id and type:
|
||||
$this->getSessionInfo();
|
||||
|
||||
// is there a user logged in?
|
||||
$username = ( !empty($INFO['userinfo']) && !empty($INFO['userinfo']['name']) ? $INFO['userinfo']['name'] : '');
|
||||
|
||||
// build the tracker code:
|
||||
$code = "document._botmon = {t0: Date.now(), session: " . json_encode($this->sessionId) . ", seed: " . json_encode($this->getConf('captchaSeed')) . ", ip: " . json_encode($_SERVER['REMOTE_ADDR']) . "};" . NL;
|
||||
if ($username) {
|
||||
$code .= DOKU_TAB . DOKU_TAB . 'document._botmon.user = "' . $username . '";'. NL;
|
||||
}
|
||||
$code = $this->getBMHeader();
|
||||
|
||||
// add the deferred script loader::
|
||||
$code .= DOKU_TAB . DOKU_TAB . "addEventListener('DOMContentLoaded', function(){" . NL;
|
||||
@@ -78,6 +78,22 @@ class action_plugin_botmon extends DokuWiki_Action_Plugin {
|
||||
$event->data['script'][] = ['_data' => $code];
|
||||
}
|
||||
|
||||
/* create the BM object code for insertion into a script element: */
|
||||
private function getBMHeader() {
|
||||
|
||||
// build the tracker code:
|
||||
$code = DOKU_TAB . DOKU_TAB . "document._botmon = {t0: Date.now(), session: " . json_encode($this->sessionId) . ", seed: " . json_encode($this->getConf('captchaSeed')) . ", ip: " . json_encode($_SERVER['REMOTE_ADDR']) . "};" . NL;
|
||||
|
||||
// is there a user logged in?
|
||||
$username = ( !empty($INFO['userinfo']) && !empty($INFO['userinfo']['name']) ? $INFO['userinfo']['name'] : '');
|
||||
if ($username) {
|
||||
$code .= DOKU_TAB . DOKU_TAB . 'document._botmon.user = "' . $username . '";'. NL;
|
||||
}
|
||||
|
||||
return $code;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts tracking code to the page header
|
||||
* (only called on 'show' actions)
|
||||
@@ -120,7 +136,8 @@ class action_plugin_botmon extends DokuWiki_Action_Plugin {
|
||||
substr($conf['lang'],0,2), /* page language */
|
||||
implode(',', array_unique(array_map( function($it) { return substr(trim($it),0,2); }, explode(',',trim($_SERVER['HTTP_ACCEPT_LANGUAGE'], " \t;,*"))))), /* accepted client languages */
|
||||
$this->getCountryCode(), /* GeoIP country code */
|
||||
$this->showCaptcha /* show captcha? */ );
|
||||
$this->showCaptcha /* show captcha? */
|
||||
);
|
||||
|
||||
//* create the log line */
|
||||
$filename = __DIR__ .'/logs/' . gmdate('Y-m-d') . '.srv.txt'; /* use GMT date for filename */
|
||||
@@ -182,37 +199,68 @@ class action_plugin_botmon extends DokuWiki_Action_Plugin {
|
||||
$this->sessionId = $_SERVER['REMOTE_ADDR'];
|
||||
$this->sessionType = 'ip';
|
||||
}
|
||||
if (!$this->sessionId) { /* if everything else fails, just us a random ID */
|
||||
$this->sessionId = rand(1000000, 9999999);
|
||||
$this->sessionType = 'rand';
|
||||
}
|
||||
}
|
||||
|
||||
public function showCaptcha(Event $event) {
|
||||
|
||||
$useCaptcha = $this->getConf('useCaptcha');
|
||||
|
||||
if ($useCaptcha !== 'disabled' && $this->checkCaptchaCookie() && !$this->captchaWhitelisted()) {
|
||||
$cCode = '-';
|
||||
if ($useCaptcha !== 'disabled') {
|
||||
if ($this->captchaWhitelisted()) {
|
||||
$cCode = 'W'; // whitelisted
|
||||
} elseif ($this->hasCaptchaCookie()) {
|
||||
$cCode = 'N'; // user already has a cookie
|
||||
} else {
|
||||
$cCode = 'Y'; // show the captcha
|
||||
|
||||
$this->showCaptcha = 'Y'; // captcha will be shown.
|
||||
|
||||
echo '<h1 class="sectionedit1">'; tpl_pagetitle(); echo "</h1>\n"; // always show the original page title
|
||||
$event->preventDefault(); // don't show normal content
|
||||
switch ($useCaptcha) {
|
||||
case 'blank':
|
||||
$this->insertBlankBox(); // show dada filler instead of text
|
||||
break;
|
||||
case 'dada':
|
||||
$this->insertDadaFiller(); // show dada filler instead of text
|
||||
break;
|
||||
echo '<h1 class="sectionedit1">'; tpl_pagetitle(); echo "</h1>\n"; // always show the original page title
|
||||
$event->preventDefault(); // don't show normal content
|
||||
switch ($useCaptcha) {
|
||||
case 'blank':
|
||||
$this->insertBlankBox(); // show dada filler instead of text
|
||||
break;
|
||||
case 'dada':
|
||||
$this->insertDadaFiller(); // show dada filler instead of text
|
||||
break;
|
||||
}
|
||||
$this->insertCaptchaLoader(); // and load the captcha
|
||||
}
|
||||
$this->insertCaptchaLoader(); // and load the captcha
|
||||
} else {
|
||||
$this->showCaptcha = 'N'; // do not show a captcha
|
||||
}
|
||||
$this->showCaptcha = $cCode; // store the captcha code for the logfile
|
||||
|
||||
}
|
||||
|
||||
private function checkCaptchaCookie() {
|
||||
public function showImageCaptcha(Event $event, $param) {
|
||||
|
||||
$useCaptcha = $this->getConf('useCaptcha');
|
||||
|
||||
echo '<script>' . $this->getBMHeader($event, $param) . '</script>';
|
||||
|
||||
$cCode = '-';
|
||||
if ($useCaptcha !== 'disabled') {
|
||||
if ($this->captchaWhitelisted()) {
|
||||
$cCode = 'W'; // whitelisted
|
||||
}
|
||||
elseif ($this->hasCaptchaCookie()) {
|
||||
$cCode = 'N'; // user already has a cookie
|
||||
}
|
||||
else {
|
||||
$cCode = 'Y'; // show the captcha
|
||||
|
||||
echo '<svg width="100%" height="100%" viewBox="0 0 800 400" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M1,1l798,398" style="fill:none;stroke:#f00;stroke-width:1px;"/><path d="M1,399l798,-398" style="fill:none;stroke:#f00;stroke-width:1px;"/><rect x="1" y="1" width="798" height="398" style="fill:none;stroke:#000;stroke-width:1px;"/></svg>'; // placeholder image
|
||||
$event->preventDefault(); // don't show normal content
|
||||
|
||||
// TODO Insert dummy image
|
||||
$this->insertCaptchaLoader(); // and load the captcha
|
||||
}
|
||||
};
|
||||
|
||||
$this->showCaptcha = $cCode; // store the captcha code for the logfile
|
||||
}
|
||||
|
||||
private function hasCaptchaCookie() {
|
||||
|
||||
$cookieVal = isset($_COOKIE['DWConfirm']) ? $_COOKIE['DWConfirm'] : null;
|
||||
|
||||
@@ -223,7 +271,7 @@ class action_plugin_botmon extends DokuWiki_Action_Plugin {
|
||||
|
||||
//echo '<ul><li>cookie: ' . $cookieVal . '</li><li>expected: ' . $expected . '</li><li>matches: ' .($cookieVal == $expected ? 'true' : 'false') . '</li></ul>';
|
||||
|
||||
return $cookieVal !== $expected;
|
||||
return $cookieVal == $expected;
|
||||
}
|
||||
|
||||
// check if the visitor's IP is on a whitelist:
|
||||
@@ -251,15 +299,13 @@ class action_plugin_botmon extends DokuWiki_Action_Plugin {
|
||||
$to = inet_pton($col[1]);
|
||||
|
||||
if ($ip >= $from && $ip <= $to) {
|
||||
//echo "<p>Found my IP in range: " . $col[0] . " - " . $col[1] . "</p>";
|
||||
return true;
|
||||
return true; /* IP whitelisted */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return false; /* IP not found in whitelist */
|
||||
}
|
||||
|
||||
private function insertCaptchaLoader() {
|
||||
|
||||
21
admin.css
21
admin.css
@@ -108,6 +108,12 @@
|
||||
&.cl_operaold::before { background-position-y: -380px }
|
||||
&.cl_other::before { background-image: url('img/more.svg') }
|
||||
|
||||
/* Captcha statuses */
|
||||
&.captcha::before { background-image: url('img/captcha.png') }
|
||||
&.cap_Y::before { background-position-y: -20px }
|
||||
&.cap_YN::before { background-position-y: -40px }
|
||||
&.cap_W::before { background-position-y: -60px }
|
||||
|
||||
/* Country flags */
|
||||
/* Note: flag images and CSS adapted from: https://github.com/lafeber/world-flags-sprite/ */
|
||||
&.country::before {
|
||||
@@ -730,21 +736,28 @@
|
||||
background-image: url('img/info.svg')
|
||||
}
|
||||
|
||||
/* pageviews */
|
||||
span.pageviews {
|
||||
/* pages seen */
|
||||
span.pageseen, span.pageviews {
|
||||
border: #999 solid 1px;
|
||||
padding: 0 2px;
|
||||
font-size: smaller;
|
||||
border-radius: .5em;
|
||||
margin-right: .25em;
|
||||
}
|
||||
span.pageviews::before {
|
||||
span.pageseen::before {
|
||||
content : '';
|
||||
display: inline-block;
|
||||
width: 1.25em; height: 1.25em;
|
||||
background: transparent url('img/page.svg') center no-repeat;
|
||||
background-size: 1.25em;
|
||||
}
|
||||
span.pageviews::before {
|
||||
content : '';
|
||||
display: inline-block;
|
||||
width: 1.25em; height: 1.25em;
|
||||
background: transparent url('img/views.svg') center no-repeat;
|
||||
background-size: 1.25em;
|
||||
}
|
||||
}
|
||||
|
||||
/* item footer */
|
||||
@@ -890,7 +903,7 @@
|
||||
border-top-color: #CCC;
|
||||
}
|
||||
}
|
||||
span.pageviews {
|
||||
span.pageseen, span.pageviews {
|
||||
border-color: #555;
|
||||
}
|
||||
|
||||
|
||||
162
admin.js
162
admin.js
@@ -291,7 +291,7 @@ BotMon.live = {
|
||||
// shortcut to make code more readable:
|
||||
const model = BotMon.live.data.model;
|
||||
|
||||
const timeout = 60 * 60 * 1000; // session timeout: One hour
|
||||
//const timeout = 60 * 60 * 1000; // session timeout: One hour
|
||||
|
||||
if (visitor._type == BM_USERTYPE.KNOWN_BOT) { // known bots match by their bot ID:
|
||||
|
||||
@@ -303,13 +303,14 @@ BotMon.live = {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
} else { // other types match by their DW/PHPIDs:
|
||||
|
||||
// loop over all visitors already registered and check for ID matches:
|
||||
for (let i=0; i<model._visitors.length; i++) {
|
||||
const v = model._visitors[i];
|
||||
|
||||
if ( v.id == visitor.id) { // match the DW/PHP IDs
|
||||
if ( v.id.trim() !== '' && v.id == visitor.id) { // match the DW/PHP IDs
|
||||
return v;
|
||||
}
|
||||
}
|
||||
@@ -379,21 +380,35 @@ BotMon.live = {
|
||||
// check if it already exists:
|
||||
let visitor = model.findVisitor(nv, type);
|
||||
if (!visitor) {
|
||||
visitor = nv;
|
||||
visitor._seenBy = [type];
|
||||
visitor._pageViews = []; // array of page views
|
||||
visitor._hasReferrer = false; // has at least one referrer
|
||||
visitor._jsClient = false; // visitor has been seen logged by client js as well
|
||||
visitor._client = BotMon.live.data.clients.match(nv.agent) ?? null; // client info
|
||||
visitor._platform = BotMon.live.data.platforms.match(nv.agent); // platform info
|
||||
visitor = {...nv, ...{
|
||||
_seenBy: [type],
|
||||
_viewCount: 0, // number of page views
|
||||
_loadCount: 0, // number of page loads (not necessarily views!)
|
||||
_pageViews: [], // array of page views
|
||||
_hasReferrer: false, // has at least one referrer
|
||||
_jsClient: false, // visitor has been seen logged by client js as well
|
||||
_client: BotMon.live.data.clients.match(nv.agent) ?? null, // client info
|
||||
_platform: BotMon.live.data.platforms.match(nv.agent), // platform info
|
||||
_captcha: {'-': 0, 'Y': 0, 'N': 0, 'W':0} // captcha counter
|
||||
}};
|
||||
model._visitors.push(visitor);
|
||||
} else { // update existing
|
||||
if (visitor._firstSeen > nv.ts) {
|
||||
visitor._firstSeen = nv.ts;
|
||||
}
|
||||
};
|
||||
|
||||
// update first and last seen:
|
||||
if (visitor._firstSeen > nv.ts) {
|
||||
visitor._firstSeen = nv.ts;
|
||||
}
|
||||
if (visitor._lastSeen < nv.ts) {
|
||||
visitor._lastSeen = nv.ts;
|
||||
}
|
||||
|
||||
// find browser
|
||||
// update total loads and views (not the same!):
|
||||
visitor._loadCount += 1;
|
||||
visitor._viewCount += (nv.captcha == 'Y' ? 0 : 1);
|
||||
|
||||
// ...because also a captcha is a "load", but not a "view".
|
||||
// let's count the captcha statuses as well:
|
||||
if (nv.captcha) visitor._captcha[nv.captcha] += 1;
|
||||
|
||||
// is this visit already registered?
|
||||
let prereg = model._getPageView(visitor, nv);
|
||||
@@ -401,14 +416,15 @@ BotMon.live = {
|
||||
// add new page view:
|
||||
prereg = model._makePageView(nv, type);
|
||||
visitor._pageViews.push(prereg);
|
||||
} else {
|
||||
// update last seen date
|
||||
prereg._lastSeen = nv.ts;
|
||||
// increase view count:
|
||||
prereg._viewCount += 1;
|
||||
prereg._tickCount += 1;
|
||||
}
|
||||
|
||||
// update last seen date
|
||||
prereg._lastSeen = nv.ts;
|
||||
|
||||
// increase view count:
|
||||
prereg._loadCount += (visitor.captcha == 'Y' ? 0 : 1);
|
||||
//prereg._tickCount += 1;
|
||||
|
||||
// update referrer state:
|
||||
visitor._hasReferrer = visitor._hasReferrer ||
|
||||
(prereg.ref !== undefined && prereg.ref !== '');
|
||||
@@ -520,7 +536,8 @@ BotMon.live = {
|
||||
_lastSeen: data.ts,
|
||||
_seenBy: [type],
|
||||
_jsClient: ( type !== BM_LOGTYPE.SERVER),
|
||||
_viewCount: 1,
|
||||
_viewCount: 0,
|
||||
_loadCount: 0,
|
||||
_tickCount: 0
|
||||
};
|
||||
}
|
||||
@@ -572,19 +589,19 @@ BotMon.live = {
|
||||
|
||||
// count visits and page views:
|
||||
this.data.totalVisits += 1;
|
||||
this.data.totalPageViews += v._pageViews.length;
|
||||
this.data.totalPageViews += v._viewCount;
|
||||
|
||||
// check for typical bot aspects:
|
||||
let botScore = 0;
|
||||
|
||||
if (v._type == BM_USERTYPE.KNOWN_BOT) { // known bots
|
||||
|
||||
this.data.bots.known += v._pageViews.length;
|
||||
this.data.bots.known += v._viewCount;
|
||||
this.groups.knownBots.push(v);
|
||||
|
||||
} else if (v._type == BM_USERTYPE.KNOWN_USER) { // known users */
|
||||
|
||||
this.data.bots.users += v._pageViews.length;
|
||||
this.data.bots.users += v._viewCount;
|
||||
this.groups.users.push(v);
|
||||
|
||||
} else {
|
||||
@@ -596,11 +613,11 @@ BotMon.live = {
|
||||
|
||||
if (e.isBot) { // likely bots
|
||||
v._type = BM_USERTYPE.LIKELY_BOT;
|
||||
this.data.bots.suspected += v._pageViews.length;
|
||||
this.data.bots.suspected += v._viewCount;
|
||||
this.groups.suspectedBots.push(v);
|
||||
} else { // probably humans
|
||||
v._type = BM_USERTYPE.PROBABLY_HUMAN;
|
||||
this.data.bots.human += v._pageViews.length;
|
||||
this.data.bots.human += v._viewCount;
|
||||
this.groups.humans.push(v);
|
||||
}
|
||||
}
|
||||
@@ -640,7 +657,7 @@ BotMon.live = {
|
||||
//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;
|
||||
return b._viewCount - a._viewCount;
|
||||
});
|
||||
|
||||
const other = {
|
||||
@@ -659,12 +676,12 @@ BotMon.live = {
|
||||
rList.push({
|
||||
id: it._bot.id,
|
||||
name: (it._bot.n ? it._bot.n : it._bot.id),
|
||||
count: it._pageViews.length
|
||||
count: it._viewCount
|
||||
});
|
||||
} else {
|
||||
other.count += it._pageViews.length;
|
||||
};
|
||||
total += it._pageViews.length;
|
||||
total += it._viewCount;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -997,7 +1014,7 @@ BotMon.live = {
|
||||
const list = me.groups[type];
|
||||
|
||||
list.forEach(it => {
|
||||
bounces += (it._pageViews.length <= 1 ? 1 : 0);
|
||||
bounces += (it._viewCount <= 1 ? 1 : 0);
|
||||
});
|
||||
|
||||
return bounces;
|
||||
@@ -1085,7 +1102,7 @@ BotMon.live = {
|
||||
}
|
||||
|
||||
// add to counter:
|
||||
ipRec.count += v._pageViews.length;
|
||||
ipRec.count += v._viewCount;
|
||||
|
||||
},
|
||||
|
||||
@@ -1520,12 +1537,13 @@ BotMon.live = {
|
||||
|
||||
// are there at lest num pages loaded?
|
||||
smallPageCount: function(visitor, num) {
|
||||
return (visitor._pageViews.length <= Number(num));
|
||||
return (visitor._viewCount <= Number(num));
|
||||
},
|
||||
|
||||
// There was no entry in a specific log file for this visitor:
|
||||
// note that this will also trigger the "noJavaScript" rule:
|
||||
noRecord: function(visitor, type) {
|
||||
if (!visitor._seenBy.includes('srv')) return false; // only if 'srv' is also specified!
|
||||
return !visitor._seenBy.includes(type);
|
||||
},
|
||||
|
||||
@@ -1613,7 +1631,7 @@ BotMon.live = {
|
||||
// At least x page views were recorded, but they come within less than y seconds
|
||||
loadSpeed: function(visitor, minItems, maxTime) {
|
||||
|
||||
if (visitor._pageViews.length >= minItems) {
|
||||
if (visitor._viewCount >= minItems) {
|
||||
//console.log('loadSpeed', visitor._pageViews.length, minItems, maxTime);
|
||||
|
||||
const pvArr = visitor._pageViews.map(pv => pv._lastSeen).sort();
|
||||
@@ -1704,7 +1722,7 @@ BotMon.live = {
|
||||
switch (type) {
|
||||
case "srv":
|
||||
typeName = "Server";
|
||||
columns = ['ts','ip','pg','id','typ','usr','agent','ref','lang','accept','geo'];
|
||||
columns = ['ts','ip','pg','id','typ','usr','agent','ref','lang','accept','geo','captcha'];
|
||||
break;
|
||||
case "log":
|
||||
typeName = "Page load";
|
||||
@@ -2299,20 +2317,11 @@ BotMon.live = {
|
||||
}, data.id));
|
||||
}
|
||||
|
||||
// seen by icon:
|
||||
span1.appendChild(make('span', {
|
||||
'class': 'icon_only seenby sb_' + data._seenBy.join(''),
|
||||
'title': "Seen by: " + data._seenBy.join('+')
|
||||
}, data._seenBy.join(', ')));
|
||||
span1.appendChild(make('span', { /* page views */
|
||||
'class': 'has_icon pageseen',
|
||||
'title': data._pageViews.length + " page load(s)"
|
||||
}, data._pageViews.length));
|
||||
|
||||
// country flag:
|
||||
if (data.geo && data.geo !== 'ZZ') {
|
||||
span1.appendChild(make('span', {
|
||||
'class': 'icon_only country ctry_' + data.geo.toLowerCase(),
|
||||
'data-ctry': data.geo,
|
||||
'title': "Country: " + ( data._country || "Unknown")
|
||||
}, ( data._country || "Unknown") ));
|
||||
}
|
||||
|
||||
// referer icons:
|
||||
if ((data._type == BM_USERTYPE.PROBABLY_HUMAN || data._type == BM_USERTYPE.LIKELY_BOT) && data.ref) {
|
||||
@@ -2326,15 +2335,26 @@ BotMon.live = {
|
||||
summary.appendChild(span1);
|
||||
const span2 = make('span'); /* right-hand group */
|
||||
|
||||
span2.appendChild(make('span', { /* first-seen */
|
||||
'class': 'has_iconfirst-seen',
|
||||
'title': "First seen: " + data._firstSeen.toLocaleString() + " UTC"
|
||||
}, BotMon.t._formatTime(data._firstSeen)));
|
||||
// country flag:
|
||||
if (data.geo && data.geo !== 'ZZ') {
|
||||
span2.appendChild(make('span', {
|
||||
'class': 'icon_only country ctry_' + data.geo.toLowerCase(),
|
||||
'data-ctry': data.geo,
|
||||
'title': "Country: " + ( data._country || "Unknown")
|
||||
}, ( data._country || "Unknown") ));
|
||||
}
|
||||
|
||||
span2.appendChild(make('span', { /* page views */
|
||||
'class': 'has_icon pageviews',
|
||||
'title': data._pageViews.length + " page view(s)"
|
||||
}, data._pageViews.length));
|
||||
span2.appendChild(make('span', { // seen-by icon:
|
||||
'class': 'icon_only seenby sb_' + data._seenBy.join(''),
|
||||
'title': "Seen by: " + data._seenBy.join('+')
|
||||
}, data._seenBy.join(', ')));
|
||||
|
||||
const captchaCode = '' + ( data._captcha['Y'] > 0 ? 'Y' : '' ) + ( data._captcha['N'] > 0 ? 'N' : '' ) + ( data._captcha['W'] > 0 ? 'W' : '' );
|
||||
if (captchaCode !== '') {
|
||||
span2.appendChild(make('span', { // captcha status
|
||||
'class': 'icon_only captcha cap_' + captchaCode,
|
||||
}, captchaCode));
|
||||
}
|
||||
|
||||
summary.appendChild(span2);
|
||||
|
||||
@@ -2414,6 +2434,13 @@ BotMon.live = {
|
||||
dl.appendChild(make('dd', {'class': 'lastSeen'}, data._lastSeen.toLocaleString()));
|
||||
}
|
||||
|
||||
dl.appendChild(make('dt', {}, "Actions:"));
|
||||
dl.appendChild(make('dd', {'class': 'views'},
|
||||
"Page loads: " + data._loadCount.toString() +
|
||||
( data._captcha['Y'] > 0 || data._captcha['W'] || data._captcha['-'] > 0 ? ", captchas: " + (data._captcha['Y']+data._captcha['W']+data._captcha['-']).toString() : '') +
|
||||
", views: " + data._viewCount.toString()
|
||||
));
|
||||
|
||||
dl.appendChild(make('dt', {}, "User-Agent:"));
|
||||
dl.appendChild(make('dd', {'class': 'agent'}, data.agent));
|
||||
|
||||
@@ -2441,6 +2468,12 @@ BotMon.live = {
|
||||
'title': "Country: " + data._country
|
||||
}, data._country + ' (' + data.geo + ')'));
|
||||
}
|
||||
if (data.captcha && data.captcha !=='') {
|
||||
dl.appendChild(make('dt', {}, "Captcha-status:"));
|
||||
dl.appendChild(make('dd', {
|
||||
'class': 'captcha'
|
||||
}, data.captcha));
|
||||
}
|
||||
|
||||
dl.appendChild(make('dt', {}, "Session ID:"));
|
||||
dl.appendChild(make('dd', {'class': 'has_icon session typ_' + data.typ}, data.id));
|
||||
@@ -2528,12 +2561,19 @@ BotMon.live = {
|
||||
'title': "PageID: " + page.pg
|
||||
}, page.pg)); /* DW Page ID */
|
||||
|
||||
// get the time difference:
|
||||
row1.appendChild(make('span', {
|
||||
'class': 'first-seen',
|
||||
'title': "First visited: " + page._firstSeen.toLocaleString() + " UTC"
|
||||
}, BotMon.t._formatTime(page._firstSeen)));
|
||||
|
||||
const rightGroup = row1.appendChild(make('div')); // right-hand group
|
||||
|
||||
// get the time difference:
|
||||
rightGroup.appendChild(make('span', {
|
||||
'class': 'first-seen',
|
||||
'title': "First visited: " + page._firstSeen.toLocaleString() + " UTC"
|
||||
}, BotMon.t._formatTime(page._firstSeen)));
|
||||
|
||||
rightGroup.appendChild(make('span', { /* page loads */
|
||||
'class': 'has_icon pageviews',
|
||||
'title': page._viewCount.toString() + " page load(s)"
|
||||
}, page._viewCount.toString()));
|
||||
|
||||
pgLi.appendChild(row1);
|
||||
|
||||
/* LINE 2 */
|
||||
|
||||
33
captcha.js
33
captcha.js
@@ -26,7 +26,7 @@ const $BMCaptcha = {
|
||||
|
||||
// Checkbox:
|
||||
const lbl = document.createElement('label');
|
||||
lbl.innerHTML = '<span class="confirm">Click to confirm.</span><span class="busy"></span><span class="checking">Checking …</span><span class="loading">Loading …</span>';
|
||||
lbl.innerHTML = '<span class="confirm">Click to confirm.</span><span class="busy"></span><span class="checking">Checking …</span><span class="loading">Loading …</span><span class="erricon">�</span><span class="error">An error occured.</span>';
|
||||
const cb = document.createElement('input');
|
||||
cb.setAttribute('type', 'checkbox');
|
||||
cb.setAttribute('disabled', 'disabled');
|
||||
@@ -152,26 +152,35 @@ const $BMCaptcha = {
|
||||
if (e.target.checked) {
|
||||
//document.getElementById('botmon_captcha_box').close();
|
||||
|
||||
const dat = [ // the data to encode
|
||||
document._botmon.seed || '',
|
||||
location.hostname,
|
||||
document._botmon.ip || '0.0.0.0',
|
||||
(document._botmon.t0 ? new Date(document._botmon.t0) : new Date()).toISOString().substring(0, 10)
|
||||
];
|
||||
const hash = $BMCaptcha.digest.hash(dat.join('|'));
|
||||
try {
|
||||
var $status = 'loading';
|
||||
|
||||
// set the cookie:
|
||||
document.cookie = "DWConfirm=" + hash + ';path=/;';
|
||||
// generate the hash:
|
||||
const dat = [ // the data to encode
|
||||
document._botmon.seed || '',
|
||||
location.hostname,
|
||||
document._botmon.ip || '0.0.0.0',
|
||||
(new Date()).toISOString().substring(0, 10)
|
||||
];
|
||||
const hash = $BMCaptcha.digest.hash(dat.join('|'));
|
||||
|
||||
// set the cookie:
|
||||
document.cookie = "DWConfirm=" + hash + ';path=/;';
|
||||
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
$status = 'error';
|
||||
}
|
||||
|
||||
// change the interface:
|
||||
const dlg = document.getElementById('botmon_captcha_box');
|
||||
if (dlg) {
|
||||
dlg.classList.remove('ready');
|
||||
dlg.classList.add('loading');
|
||||
dlg.classList.add( $status );
|
||||
}
|
||||
|
||||
// reload the page:
|
||||
window.location.reload(true);
|
||||
if ($status !== 'error')window.location.reload(true);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
*/
|
||||
|
||||
$conf['geoiplib'] = 'disabled';
|
||||
$conf['useCaptcha'] = 0;
|
||||
$conf['captchaSeed'] = 'b472719ba5634d378a7d7f9bfc46659f';
|
||||
$conf['useCaptcha'] = 'disabled';
|
||||
$conf['captchaSeed'] = 'c53bc5f94929451987efa6c768d8856b';
|
||||
|
||||
@@ -335,6 +335,12 @@
|
||||
2001:4860:4801:000c:: 2001:4860:4801:000c:FFFF:FFFF:FFFF:FFFF 64
|
||||
2001:4860:4801:000f:: 2001:4860:4801:000f:FFFF:FFFF:FFFF:FFFF 64
|
||||
|
||||
# PlagAware Bot - from previous visits’ IPs
|
||||
157.90.90.163 157.90.90.163 32
|
||||
2a01:4f8:2190:21a0::2 2a01:4f8:2190:21a0::2 64
|
||||
# SeznamBot - IPs from: https://o-seznam.cz/napoveda/vyhledavani/en/seznambot-crawler/
|
||||
77.75.76.0 77.75.79.255 22
|
||||
2a02:0598:0064:8a00:0000:0000:3100:0000 2a02:0598:0064:8a00:0000:0000:3100:001f 123
|
||||
2a02:0598:0128:8a00:0000:0000:0b00:0000 2a02:0598:0128:8a00:0000:0000:0b00:001f 123
|
||||
2a02:0598:0096:8a00:0000:0000:1200:0120 2a02:0598:0096:8a00:0000:0000:1200:013f 123
|
||||
|
||||
# localhosts
|
||||
127.0.0.1 127.255.255.255 8
|
||||
::1 ::1 128
|
||||
@@ -1,10 +1,12 @@
|
||||
{
|
||||
"groups": [
|
||||
{"id": "alibaba", "name": "Alibaba"},
|
||||
{"id": "amazon", "name": "Amazon DS"},
|
||||
{"id": "amazon", "name": "Amazon"},
|
||||
{"id": "bezeq", "name": "Bezeq Int."},
|
||||
{"id": "brasilnet", "name": "BrasilNet"},
|
||||
{"id": "charter", "name": "Charter Inc."},
|
||||
{"id": "chinanet", "name": "Chinanet"},
|
||||
{"id": "cloudflare", "name": "Cloudflare Inc."},
|
||||
{"id": "cnisp", "name": "China ISP"},
|
||||
{"id": "cnmob", "name": "China Mobile"},
|
||||
{"id": "google", "name": "Google LLC"},
|
||||
@@ -44,7 +46,7 @@
|
||||
{"from": "52.96.0.0", "to": "52.127.255.254", "m": 11, "g": "microsoft"},
|
||||
{"from": "54.0.0.0", "to": "54.255.255.254", "m": 8, "g": "amazon"},
|
||||
{"from": "66.249.64.0", "to": "66.249.95.254", "m": 19, "g": "google"},
|
||||
{"from": "84.37.35.0", "to": "84.37.255.254", "g": "gtt"},
|
||||
{"from": "82.80.0.0", "to": "82.81.255.255", "m": 15, "g": "bezeq"},
|
||||
{"from": "94.74.64.0", "to": "94.74.127.254", "m": 18, "g": "huawei"},
|
||||
{"from": "91.84.96.0", "to": "91.84.127.254", "m": 19, "g": "vdsina"},
|
||||
{"from": "101.0.0.0", "to": "101.255.255.254", "m": 8,"g": "chinanet"},
|
||||
@@ -98,6 +100,7 @@
|
||||
{"from": "2603:8000::::::", "to": "2603:80ff:ffff:ffff:ffff:ffff:ffff:ffff", "m": 24, "g": "charter"},
|
||||
{"from": "2607:a400::::::", "to": "2607:a400:ffff:ffff:ffff:ffff:ffff:ffff", "m": 32, "g": "zenlayer"},
|
||||
{"from": "2804:::::::", "to": "2804:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF", "m": 16, "g": "misc_sa"},
|
||||
{"from": "2a09:bac3::::::", "to": "2a09:bac3:ffff:ffff:ffff:ffff:ffff:ffff", "m": 32,"g": "cloudflare"},
|
||||
{"from": "2a0a:4cc0::::::", "to": "2a0a:4cc0:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF", "g": "netcup"}
|
||||
]
|
||||
}
|
||||
BIN
img/captcha.png
Normal file
BIN
img/captcha.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.6 KiB |
BIN
img/stages.png
BIN
img/stages.png
Binary file not shown.
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 4.1 KiB |
@@ -232,7 +232,7 @@ weiter 13
|
||||
gleich 13
|
||||
gute 13
|
||||
vom 13
|
||||
Warte 12
|
||||
warte 12
|
||||
deinen 12
|
||||
ins 12
|
||||
denke 12
|
||||
@@ -2730,4 +2730,5 @@ zahle 1
|
||||
brauchten 1
|
||||
stinkt 1
|
||||
treiben 1
|
||||
welch 1
|
||||
welch 1
|
||||
Warte 1
|
||||
|
||||
22
style.less
22
style.less
@@ -4,11 +4,17 @@ body.botmon_captcha {
|
||||
color: transparent !important;
|
||||
text-shadow: 0 0 .25em rgba(0,.0,0,.8);
|
||||
}
|
||||
p, h2, h3, h4, h5, h6 {
|
||||
p, dt, dd, h2, h3, h4, h5, h6, a:link, a:visited {
|
||||
color: transparent !important;
|
||||
text-shadow: 0 0 .35em rgba(0,0,0,.5);
|
||||
user-select: none;
|
||||
}
|
||||
svg {
|
||||
width: auto; height: auto;
|
||||
-webkit-filter: blur(8px); /* For Safari */
|
||||
filter: blur(8px);
|
||||
}
|
||||
|
||||
}
|
||||
#botmon_captcha_box {
|
||||
& {
|
||||
@@ -58,6 +64,9 @@ body.botmon_captcha {
|
||||
background: transparent url('img/busy-light.svg') center no-repeat;
|
||||
background-size: 24px;
|
||||
}
|
||||
span.error, span.erricon {
|
||||
color: #f96c6c;
|
||||
}
|
||||
}
|
||||
input[type="checkbox"] {
|
||||
width: 24px; height: 24px;
|
||||
@@ -74,20 +83,25 @@ body.botmon_captcha {
|
||||
display: none;
|
||||
}
|
||||
&.checking {
|
||||
input[type="checkbox"], span.confirm, span.loading { display: none;}
|
||||
input[type="checkbox"], span.confirm, span.loading, span.erricon, span.error { display: none;}
|
||||
span.busy, span.checking { display: initial; }
|
||||
label, input[type="checkbox"] { cursor: wait; }
|
||||
}
|
||||
&.ready {
|
||||
input[type="checkbox"], span.confirm { display: initial;}
|
||||
span.busy, span.checking, span.loading { display: none; }
|
||||
span.busy, span.checking, span.loading, span.erricon, span.error { display: none; }
|
||||
label, input[type="checkbox"] { cursor: pointer; }
|
||||
}
|
||||
&.loading {
|
||||
span.busy, span.loading { display: initial; }
|
||||
input[type="checkbox"], span.confirm, span.checking { display: none;}
|
||||
input[type="checkbox"], span.confirm, span.checking, span.erricon, span.error { display: none;}
|
||||
label { cursor: wait; }
|
||||
}
|
||||
&.error {
|
||||
span.erricon, span.error { display: initial; }
|
||||
input[type="checkbox"], span.confirm, span.checking, span.busy, span.loading { display: none;}
|
||||
label { cursor: initial; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user