diff --git a/data/known-clients.json b/data/known-clients.json
index dbabeee..bb3e389 100644
--- a/data/known-clients.json
+++ b/data/known-clients.json
@@ -3,9 +3,13 @@
"id": "opera",
"rx": [ "\\sOpera\\/.*?Version\\/(\\S+)", "Opera\\/(\\S+)" ]
},
+ {"n": "AOL Explorer",
+ "id": "aol",
+ "rx": [ "\\sAOL\\s(\\d+\\.\\d+)\\)", "\\sAOLBUILD\\/(\\S+)", "\\sBukaolshop\\s", "\\.aolapp\\/(\\d+\\.\\d+)\\." ]
+ },
{"n": "Samsung Internet",
"id": "samsung",
- "rx": [ "\\sSamsungBrowser\\/(\\S+)" ]
+ "rx": [ "\\sSamsungBrowser[\\/\\s](\\d+\\.\\d+)" ]
},
{"n": "UC Browser",
"id": "uc",
diff --git a/data/known-platforms.json b/data/known-platforms.json
index 51c4f60..6b81c72 100644
--- a/data/known-platforms.json
+++ b/data/known-platforms.json
@@ -19,9 +19,13 @@
"id": "android",
"rx": [ "[\\(\\s]Android\\s([^;]+);" ]
},
+ {"n": "MacOS (old)",
+ "id": "macosold",
+ "rx": [ "\\sMac OS X (10_\\d+_\\d+)" ]
+ },
{"n": "MacOS",
"id": "macos",
- "rx": [ "\\(Macintosh;" ]
+ "rx": [ "\\sMac OS X (1[1-9]_\\d+_\\d+)" ]
},
{"n": "Vintage Windows",
"id": "winold",
diff --git a/data/rules.json b/data/rules.json
index c4368d8..060b7ee 100644
--- a/data/rules.json
+++ b/data/rules.json
@@ -1,11 +1,29 @@
{
- "ip-ranges": [
- {"range": "191.177.0.0", "mask": 16, "bot": 50}
- ],
+ "threshold": 100,
"rules": [
- {"field": "_client", "item": "id", "op": "equals", "value": "chromeold", "bot": 30}
- ],
- "thresholds": {
- "bot": 50
- }
+ {"func": "obsoleteClient",
+ "id": "oldClient", "desc": "Visit with obsolete browser version",
+ "bot": 40
+ },
+ {"func": "obsoletePlatform",
+ "id": "oldOS", "desc": "Visit with obsolete platform version",
+ "bot": 40
+ },
+ {"func": "noJavaScript",
+ "id": "noJS", "desc": "Visit with JavaScript disabled",
+ "bot": 20
+ },
+ {"func": "smallPageCount", "params": [1],
+ "id": "onePage", "desc": "Views only a single page",
+ "bot": 20
+ },
+ {"func": "noTicks",
+ "id": "noTicks", "desc": "Visitor did not spend time reading any page",
+ "bot": 10
+ },
+ {"func": "noReferences",
+ "id": "noRefs", "desc": "None of the page views came with a reference field",
+ "bot": 30
+ }
+ ]
}
\ No newline at end of file
diff --git a/img/aol.png b/img/aol.png
new file mode 100644
index 0000000..16a15fe
Binary files /dev/null and b/img/aol.png differ
diff --git a/img/chromeold.svg b/img/chromeold.svg
index 31a88aa..8160631 100644
--- a/img/chromeold.svg
+++ b/img/chromeold.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/img/macos.svg b/img/macos.svg
new file mode 100644
index 0000000..89f00e5
--- /dev/null
+++ b/img/macos.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/script.js b/script.js
index 1278677..aa35b5c 100644
--- a/script.js
+++ b/script.js
@@ -209,6 +209,8 @@ BotMon.live = {
} else if (visitor._type == BM_USERTYPE.KNOWN_USER) { /* registered users */
+ //if (visitor.id == 'fsmoe7lgqb89t92vt4ju8vdl0q') console.log(visitor);
+
// visitors match when their names match:
if ( v.usr == visitor.usr
&& v.ip == visitor.ip
@@ -219,6 +221,9 @@ BotMon.live = {
if ( v.id == visitor.id) { /* match the pre-defined IDs */
return v;
+ } else if (v.ip == visitor.ip && v.agent == visitor.agent) {
+ console.info("Visitor ID not found, using matchin IP + User-Agent instead.");
+ return v;
}
}
@@ -226,18 +231,16 @@ BotMon.live = {
return null; // nothing found
},
- /* if there is already this visit registered, return it (used for updates) */
- _getVisit: function(visit, view) {
+ /* if there is already this visit registered, return the page view item */
+ _getPageView: function(visit, view) {
// shortcut to make code more readable:
const model = BotMon.live.data.model;
-
for (let i=0; i {
@@ -494,24 +493,30 @@ BotMon.live = {
let botInfo = null;
// check for known bots:
- if (agent) {
- BotList.find(bot => {
- let r = false;
- for (let j=0; j 1 ? rxr[1] : -1)
- };
- r = true;
- break;
- }
- };
- return r;
- });
+ BotList.find(bot => {
+ let r = false;
+ for (let j=0; j 1 ? rxr[1] : -1)
+ };
+ r = true;
+ break;
+ }
+ };
+ return r;
+ });
+
+ // check for unknown bots:
+ if (!botInfo) {
+ const botmatch = agent.match(/[^\s](\w*bot)[\/\s;\),$]/i);
+ if(botmatch) {
+ botInfo = {'id': "other", 'n': "Other", "bot": botmatch[0] };
+ }
}
//console.log("botInfo:", botInfo);
@@ -928,10 +933,11 @@ BotMon.live = {
if (data._type == BM_USERTYPE.KNOWN_BOT) { /* Bot only */
+ const botName = ( data._bot && data._bot.n ? data._bot.n : "Unknown");
span1.appendChild(make('span', { /* Bot */
'class': 'bot bot_' + (data._bot ? data._bot.id : 'unknown'),
- 'title': "Bot: " + (data._bot ? data._bot.n : 'Unknown')
- }, (data._bot ? data._bot.n : 'Unknown')));
+ 'title': "Bot: " + botName
+ }, botName));
} else if (data._type == BM_USERTYPE.KNOWN_USER) { /* User only */
@@ -1000,14 +1006,14 @@ BotMon.live = {
dl.appendChild(make('dt', {}, "Platform:")); /* platform */
dl.appendChild(make('dd', {'class': 'has_icon platform_' + (data._platform ? data._platform.id : 'unknown')},
platformName + ( data._platform.v > 0 ? ' (' + data._platform.v + ')' : '' ) ));
+
+ dl.appendChild(make('dt', {}, "IP-Address:"));
+ dl.appendChild(make('dd', {'class': 'has_icon ip' + ipType}, data.ip));
+
+ dl.appendChild(make('dt', {}, "ID:"));
+ dl.appendChild(make('dd', {'class': 'has_icon ip' + data.typ}, data.id));
}
- dl.appendChild(make('dt', {}, "IP-Address:"));
- dl.appendChild(make('dd', {'class': 'has_icon ip' + ipType}, data.ip));
-
- dl.appendChild(make('dt', {}, "ID:"));
- dl.appendChild(make('dd', {'class': 'has_icon ip' + data.typ}, data.id));
-
if ((data._lastSeen - data._firstSeen) < 1) {
dl.appendChild(make('dt', {}, "Seen:"));
dl.appendChild(make('dd', {'class': 'seen'}, data._firstSeen.toLocaleString()));
@@ -1041,8 +1047,10 @@ BotMon.live = {
}
pgLi.appendChild(make('span', {}, page.pg));
- pgLi.appendChild(make('span', {}, page.ref));
- pgLi.appendChild(make('span', {}, visitTimeStr));
+ // pgLi.appendChild(make('span', {}, page.ref));
+ pgLi.appendChild(make('span', {}, ( page._seenBy ? page._seenBy.join(', ') : '—') + '; ' + page._tickCount));
+ pgLi.appendChild(make('span', {}, page._firstSeen.toLocaleString()));
+ pgLi.appendChild(make('span', {}, page._lastSeen.toLocaleString()));
pageList.appendChild(pgLi);
});
diff --git a/style.less b/style.less
index cbc3b89..f718546 100644
--- a/style.less
+++ b/style.less
@@ -229,12 +229,13 @@
span.user_known::before { background-image: url('img/user.svg') }
/* platform icons */
- span.platform_macos::before, dd.platform_macos::before { background-image: url('img/apple.svg') }
span.platform_win10::before, dd.platform_win10::before { background-image: url('img/win11.svg') }
+ span.platform_macos::before, dd.platform_macos::before { background-image: url('img/apple.svg') }
span.platform_linux::before, dd.platform_linux::before { background-image: url('img/linux.svg') }
span.platform_ios::before, dd.platform_ios::before { background-image: url('img/ios.svg') }
span.platform_android::before, dd.platform_android::before { background-image: url('img/android.svg') }
span.platform_winold::before, dd.platform_winold::before { background-image: url('img/winold.png') }
+ span.platform_macosold::before, dd.platform_macosold::before { background-image: url('img/macos.svg') }
span.platform_tizen::before, dd.platform_tizen::before { background-image: url('img/tizen.png') }
span.platform_hmos::before, dd.platform_hmos::before { background-image: url('img/hmos.svg') }
span.platform_chromium::before, dd.platform_chromium::before { background-image: url('img/chromium.svg') }
@@ -253,7 +254,8 @@
span.client_samsung::before, dd.client_samsung::before { background-image: url('img/samsung.svg') }
span.client_uc::before, dd.client_uc::before { background-image: url('img/uc.svg') }
span.client_huawei::before, dd.client_huawei::before { background-image: url('img/huawei.png') }
- span.client_vivaldi::before, dd.client_vivaldi::before { background-image: url('img/vivaldi.png') }
+ span.client_vivaldi::before, dd.client_vivaldi::before { background-image: url('img/vivaldi.svg') }
+ span.client_aol::before, dd.client_aol::before { background-image: url('img/aol.png') }
/* ip address type */
span.ip6::before, dd.ip6::before { background-image: url('img/ip6.svg') }