Several smaller improvements

This commit is contained in:
Sascha Leib
2025-09-04 23:01:46 +02:00
parent 13c9d29d29
commit f4417fde3b
25 changed files with 782 additions and 127 deletions

3
.gitignore vendored
View File

@@ -1,7 +1,4 @@
.DS_Store
*.log
*.srv
*.tck
logs/*.log.txt
logs/*.srv.txt
logs/*.tck.txt

View File

@@ -29,14 +29,14 @@
"rx": ["Applebot\\/(\\d+\\.\\d+);"],
"url": "http://www.apple.com/go/applebot"
},
{"id": "openaibots",
"n": "OpenAI/ChatGPT Bots",
{"id": "openai",
"n": "OpenAI/ChatGPT",
"r": ["OAI-SearchBot", "ChatGPT-User", "GPTBot"],
"rx": ["OAI-SearchBot\\/(\\d+\\.\\d+);", "ChatGPT-User\\/(\\d+\\.\\d+);", "GPTBot\\/(\\d+\\.\\d+);"],
"url": "https://platform.openai.com/docs/bots/"
},
{"id": "metabots",
"n": "Meta Web Crawlers",
"n": "Meta/Facebook",
"r": ["facebookexternalhit", "facebookcatalog","meta-webindexer","meta-externalads","meta-externalagent","meta-externalfetcher"],
"rx": ["facebook\\w+\\/(\\d+\\.\\d+)", "meta-\\w+\\/(\\d+\\.\\d+)"],
"url": "https://developers.facebook.com/docs/sharing/webmasters/crawler"

View File

@@ -15,6 +15,14 @@
"id": "huawei",
"rx": [ "\\sHuaweiBrowser\\/(\\d+\\.\\d+)[\\s\\.]", "\\/harmony360Browser\\/(\\d+\\.\\d+)[\\s\\.]"]
},
{"n": "DuckDuckGo",
"id": "ddg",
"rx": [ "\\sDdg\\/(\\S+)" ]
},
{"n": "Vivaldi",
"id": "vivaldi",
"rx": [ "\\sVivaldi\\/(\\d+\\.\\d+)[\\s\\.]" ]
},
{"n": "Internet Explorer",
"id": "msie",
"rx": [ "\\sMSIE\\s(\\d+\\.\\d+b?);" ],
@@ -34,16 +42,12 @@
},
{"n": "Chrome",
"id": "chrome",
"rx": [ "\\sChrome\\/(1\\d\\d\\.\\d+)[\\.\\s;]" ]
"rx": [ "\\sChrome\\/(1\\d\\d)\\.\\d+" ]
},
{"n": "Safari",
"id": "safari",
"rx": [ "\\sSafari\\/(\\S+)" ]
},
{"n": "DuckDuckGo",
"id": "ddg",
"rx": [ "\\sDdg\\/(\\S+)" ]
},
{"n": "Firefox",
"id": "firefox",
"rx": [ "\\sFirefox\\/(\\S+)" ]

View File

@@ -1,15 +1,19 @@
[
{"n": "Win10/11",
"id": "win10",
"rx": [ "\\(Windows NT (1\\d\\.\\d);" ]
"rx": [ "[\\(\\s]Windows\\sNT\\s(1\\d\\.\\d)[\\)\\s\\.;]" ]
},
{"n": "Linux",
"id": "linux",
"rx": [ "\\sLinux\\s" ]
},
{"n": "BSD",
"id": "bsd",
"rx": [ "\\sNetBSD[\\);\\s]", "\\sOpenBSD[\\);\\s]", "\\sFreeBSD[\\);\\s]" ]
},
{"n": "iOS/iPadOS",
"id": "ios",
"rx": [ "\\sFxiOS\\/(\\d+\\.\\d+)\\s", "\\sCriOS\\/(\\d+\\.\\d+)\\." ]
"rx": [ "\\sFxiOS\\/(\\d+\\.\\d+)\\s", "\\siPhone\\sOS\\s([\\d\\._]+)\\s", "\\siPadOS\\s([\\d\\._]+)\\s", "\\sCriOS\\/(\\d+\\.\\d+)\\." ]
},
{"n": "Android",
"id": "android",

BIN
img/ahrefs.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 806 B

BIN
img/anthropic.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 860 B

BIN
img/babbar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

56
img/bounce.svg Normal file
View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 24 24"
version="1.1"
id="svg1"
sodipodi:docname="bounce.svg"
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs1" />
<sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#ffffff"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
inkscape:deskcolor="#505050"
showgrid="false"
showguides="true"
inkscape:zoom="45.17"
inkscape:cx="11.932699"
inkscape:cy="11.667036"
inkscape:window-width="2880"
inkscape:window-height="1526"
inkscape:window-x="2869"
inkscape:window-y="-11"
inkscape:window-maximized="1"
inkscape:current-layer="svg1" />
<title
id="title1">arrow-down-left</title>
<metadata
id="metadata1">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:title>arrow-down-left</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<path
id="path5"
style="display:inline;stroke-linecap:round;stroke-linejoin:round;fill:#666666"
d="m 22.931849,5.9601427 -0.02539,0.011719 -5.8125,0.013672 0.855469,1.5898437 C 15.330756,9.3543246 12.785051,11.75936 11.345911,14.573424 10.624405,13.172349 9.7143282,11.824042 8.5177866,10.690612 6.6950096,8.9639776 4.4705243,7.660822 2.1720834,7.401549 a 1,1 0 0 0 -1.1054687,0.8828126 1,1 0 0 0 0.8808594,1.105469 c 1.6749782,0.188944 3.6084113,1.2487544 5.1953125,2.7519534 1.5869012,1.503199 2.8163316,3.434551 3.2421874,5.138672 a 1.0001,1.0001 0 0 0 1.941406,0 c 0.726056,-2.905413 3.583028,-5.850154 6.578125,-7.9296884 l 0.798828,1.4824224 3.210938,-4.8476566 0.02539,-0.013672 h -0.01563 z" />
<path
style="stroke-linecap:round;stroke-linejoin:round;fill:#666666"
d="m 15.587891,15.453125 a 1,1 0 0 0 -1.152344,0.818359 1,1 0 0 0 0.816406,1.152344 c 1.156437,0.197324 1.961737,0.544039 2.414063,0.867188 0.452326,0.323148 0.505938,0.560754 0.505859,0.61914 a 1.0001,1.0001 0 0 0 0,0.002 c 2e-6,-0.0463 0.02551,0.01787 -0.214844,0.210938 -0.240358,0.19307 -0.696402,0.437231 -1.300781,0.642578 -1.208759,0.410694 -2.997996,0.691337 -4.974609,0.691406 C 9.7050274,20.456962 7.9157902,20.176319 6.7070312,19.765625 6.1026518,19.560278 5.6466082,19.316117 5.40625,19.123047 5.1680967,18.931748 5.1929184,18.870194 5.1933594,18.914062 c 6.635e-4,-0.09587 0.046068,-0.303946 0.4648437,-0.609375 0.4202715,-0.306519 1.192284,-0.642512 2.3496094,-0.839843 A 1,1 0 0 0 8.8242188,16.310547 1,1 0 0 0 7.671875,15.492188 c -1.3720499,0.233943 -2.4228357,0.635294 -3.1933594,1.197265 -0.7705236,0.561972 -1.2840155,1.352686 -1.2871093,2.21875 a 1.0001,1.0001 0 0 0 0,0.0039 c 3.64e-5,0.749017 0.4452013,1.353693 0.9628906,1.769532 0.5176892,0.415838 1.1590879,0.721375 1.9101562,0.976562 1.5021367,0.510374 3.4569818,0.798753 5.6171879,0.798828 2.160205,-7.5e-5 4.115051,-0.288454 5.617187,-0.798828 0.751068,-0.255187 1.392467,-0.560723 1.910156,-0.976562 0.517226,-0.415467 0.96206,-1.019489 0.962891,-1.767579 0.0012,-0.904344 -0.553226,-1.687191 -1.34375,-2.251953 -0.790524,-0.564762 -1.864356,-0.974217 -3.240234,-1.208984 z"
id="path6" />
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

65
img/bytedance.svg Normal file
View File

@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
version="1.1"
id="svg12"
sodipodi:docname="bytedance.svg"
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs12" />
<sodipodi:namedview
id="namedview12"
pagecolor="#505050"
bordercolor="#ffffff"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
inkscape:deskcolor="#505050"
inkscape:zoom="10.671875"
inkscape:cx="47.180088"
inkscape:cy="13.961933"
inkscape:window-width="2880"
inkscape:window-height="1526"
inkscape:window-x="2869"
inkscape:window-y="-11"
inkscape:window-maximized="1"
inkscape:current-layer="g13" />
<g
id="g13"
transform="matrix(1.0242856,0,0,1.0242856,-0.61033913,-0.60713804)">
<circle
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.312569;stroke-linecap:round;stroke-linejoin:round"
id="path13"
cx="12.311351"
cy="12.308226"
r="11.715483" />
<path
d="m 5.4217749,19.688519 -3.6276479,0.9312 V 3.9967336 l 3.6276479,0.9381696 z"
fill="white"
id="path9"
style="fill:#325ab4;fill-opacity:1;stroke-width:0.48" />
<path
d="m 22.952095,20.661383 -3.63456,0.931248 V 3.0237832 l 3.63456,0.9381696 z"
fill="white"
id="path10"
style="fill:#78e6dc;fill-opacity:1;stroke-width:0.48" />
<path
d="m 11.177695,20.188871 -3.6276481,0.93816 v -9.791712 l 3.6276481,0.93816 z"
fill="white"
id="path11"
style="fill:#3c8cff;fill-opacity:1;stroke-width:0.48" />
<path
d="m 13.547791,9.8898472 3.634608,-0.938208 v 9.7917598 l -3.634608,-0.938208 z"
fill="white"
id="path12"
style="fill:#00c8d2;fill-opacity:1;stroke-width:0.48" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

70
img/ccbot.svg Normal file
View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
id="Layer_2"
data-name="Layer 2"
viewBox="0 0 24 24.000001"
version="1.1"
sodipodi:docname="ccbot.svg"
width="24"
height="24"
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview27"
pagecolor="#505050"
bordercolor="#ffffff"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
inkscape:deskcolor="#505050"
showgrid="false"
inkscape:zoom="3.75"
inkscape:cx="235.46667"
inkscape:cy="146.66667"
inkscape:window-width="2880"
inkscape:window-height="1526"
inkscape:window-x="2869"
inkscape:window-y="-11"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_2" />
<defs
id="defs1">
<style
id="style1">
.cls-1 {
fill: #103;
}
.cls-2 {
fill: #152a47;
}
</style>
</defs>
<g
id="g12"
style="fill:#000000"
transform="scale(0.08)">
<circle
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.667;stroke-linecap:round;stroke-linejoin:round"
id="path27"
cx="150"
cy="150"
r="150" />
<path
shape-rendering="auto"
class="cls-1"
d="M 36.500133,201.80397 V 98.724944 c 0,-7.853926 5.229297,-16.745727 12.554306,-20.927169 L 142.72273,19.706668 V 76.739941 L 88.304108,109.70248 c -5.229298,3.14356 -8.372864,8.8918 -8.372864,14.13107 v 57.56219 c 0,5.2293 2.614649,10.46858 6.277153,12.55431 l 56.514333,33.49145 v 52.85183 L 45.920852,220.64541 c -5.229297,-3.6625 -9.420719,-11.51643 -9.420719,-18.84144 z"
id="path11"
style="fill:#000000;stroke-width:0.997958" />
<path
shape-rendering="auto"
class="cls-1"
d="M 158.42061,280.29333 V 227.4415 l 56.51433,-33.49145 c 3.6625,-2.09571 6.27715,-7.32501 6.27715,-12.55431 v -57.56219 c 0,-5.22929 -3.14356,-10.98751 -8.37286,-14.13107 L 158.42061,76.739941 V 19.706668 l 93.66829,58.081128 c 7.32501,4.181442 12.5543,13.083223 12.5543,20.927169 V 201.794 c 0,7.325 -4.18144,15.17893 -9.42072,18.84143 l -96.80187,59.64792 z"
id="path12"
style="fill:#000000;stroke-width:0.997958" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
img/dataforseo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
img/freebsd.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

105
img/hive.svg Normal file
View File

@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="32"
height="32"
fill="none"
version="1.1"
id="svg9"
sodipodi:docname="hive.svg"
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview9"
pagecolor="#505050"
bordercolor="#ffffff"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
inkscape:deskcolor="#505050"
showgrid="false"
inkscape:zoom="23.285714"
inkscape:cx="25.294479"
inkscape:cy="12.067485"
inkscape:window-width="2880"
inkscape:window-height="1526"
inkscape:window-x="2869"
inkscape:window-y="-11"
inkscape:window-maximized="1"
inkscape:current-layer="svg9" />
<circle
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.667;stroke-linecap:round;stroke-linejoin:round"
id="path9"
cx="16"
cy="16"
r="16" />
<path
fill="url(#id-1ayeugjj6)"
d="m 14.219,1.313 c 0.754,0 1.478,0.311 2.011,0.864 0.533,0.553 0.833,1.303 0.833,2.085 v 19.915 c 0,0.782 -0.3,1.532 -0.833,2.085 -0.533,0.553 -1.257,0.864 -2.011,0.864 -0.754,0 -1.478,-0.311 -2.011,-0.864 -0.533,-0.553 -0.833,-1.303 -0.833,-2.085 V 4.261 c 0,-0.782 0.3,-1.532 0.833,-2.085 0.533,-0.553 1.257,-0.864 2.011,-0.864 z"
id="path1"
style="fill:url(#id-1ayeugjj6)"
transform="matrix(1.2008987,0,0,1.2008987,-1.0749782,-1.0755786)" />
<path
fill="url(#id-l7p4zffxf)"
d="m 5.906,6.125 c 0.754,0 1.478,0.317 2.011,0.881 C 8.45,7.57 8.75,8.335 8.75,9.132 v 10.174 c 0,0.798 -0.3,1.562 -0.833,2.126 -0.533,0.564 -1.257,0.881 -2.011,0.881 -0.754,0 -1.478,-0.317 -2.011,-0.881 C 3.362,20.868 3.062,20.103 3.062,19.306 V 9.132 C 3.062,8.334 3.362,7.57 3.895,7.006 4.428,6.442 5.152,6.125 5.906,6.125"
id="path2"
style="fill:url(#id-l7p4zffxf)"
transform="matrix(1.2008987,0,0,1.2008987,-1.0749782,-1.0755786)" />
<path
fill="url(#id-p85vlqe8q)"
d="m 22.531,6.125 c 0.754,0 1.478,0.317 2.011,0.881 0.533,0.564 0.833,1.329 0.833,2.126 v 10.174 c 0,0.798 -0.3,1.562 -0.833,2.126 -0.533,0.564 -1.257,0.881 -2.011,0.881 -0.754,0 -1.477,-0.317 -2.011,-0.881 -0.534,-0.564 -0.833,-1.329 -0.833,-2.126 V 9.132 c 0,-0.798 0.3,-1.562 0.833,-2.126 0.533,-0.564 1.257,-0.881 2.011,-0.881"
id="path3"
style="fill:url(#id-p85vlqe8q)"
transform="matrix(1.2008987,0,0,1.2008987,-1.0749782,-1.0755786)" />
<defs
id="defs9">
<linearGradient
id="id-1ayeugjj6"
x1="14.219"
x2="14.219"
y1="1.313"
y2="27.125"
gradientUnits="userSpaceOnUse">
<stop
stop-color="#175cff"
id="stop4" />
<stop
offset="1"
stop-color="#3693f9"
id="stop5" />
</linearGradient>
<linearGradient
id="id-l7p4zffxf"
x1="5.9060001"
x2="5.9060001"
y1="6.125"
y2="22.313"
gradientUnits="userSpaceOnUse">
<stop
stop-color="#175cff"
id="stop6" />
<stop
offset="1"
stop-color="#3693f9"
id="stop7" />
</linearGradient>
<linearGradient
id="id-p85vlqe8q"
x1="22.531"
x2="22.531"
y1="6.125"
y2="22.313"
gradientUnits="userSpaceOnUse">
<stop
stop-color="#175cff"
id="stop8" />
<stop
offset="1"
stop-color="#3693f9"
id="stop9" />
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
img/hunter.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 952 B

BIN
img/majestic.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
img/netestate.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

1
img/page.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>page</title><path d="M6,2A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2H6M6,4H13V9H18V20H6V4M8,12V14H16V12H8M8,16V18H13V16H8Z" style="fill:#999"/></svg>

After

Width:  |  Height:  |  Size: 231 B

49
img/perplexity.svg Normal file
View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
version="1.1"
id="svg2"
sodipodi:docname="perplexity.svg"
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs2" />
<sodipodi:namedview
id="namedview2"
pagecolor="#505050"
bordercolor="#ffffff"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
inkscape:deskcolor="#505050"
showgrid="false"
inkscape:zoom="1.4370277"
inkscape:cx="241.47064"
inkscape:cy="157.26906"
inkscape:window-width="2880"
inkscape:window-height="1526"
inkscape:window-x="2869"
inkscape:window-y="-11"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<circle
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.0457371;stroke-linecap:round;stroke-linejoin:round"
id="path2"
cx="12"
cy="12"
r="12" />
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="m 5.6010131,1.7866503 5.8165679,5.3590994 v -0.00123 -5.3455054 h 1.13226 V 7.1697326 L 18.392458,1.786651 v 6.1101691 h 2.39878 v 8.8133449 h -2.391411 v 5.440806 l -5.849986,-5.139642 v 5.19866 h -1.13226 V 17.096074 L 5.6076065,22.213351 V 16.710165 H 3.2087621 V 7.8968194 h 2.392251 z M 10.56399,9.0152455 H 4.3410154 V 15.591738 H 5.6061843 V 13.517264 Z M 6.7398016,14.013516 v 5.704156 L 11.417581,15.597621 V 9.7647634 Z M 12.58242,15.543128 V 9.7592681 l 4.679136,4.2490129 v 2.701883 h 0.006 v 2.949267 z m 5.817407,0.04861 h 1.259151 V 9.0152455 h -6.17662 l 4.917469,4.4554125 z M 17.260198,7.8968194 V 4.3592703 l -3.839573,3.5375491 z m -6.687416,0 H 6.7332728 V 4.3592703 Z"
fill="#000000"
id="path1"
style="stroke-width:0.0646414" />
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

110
img/petal.svg Normal file
View File

@@ -0,0 +1,110 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="24"
height="23.999998"
viewBox="0 0 6.3499999 6.3499992"
version="1.1"
id="svg5"
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
sodipodi:docname="petal.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<title
id="title7982">Petal Search logo</title>
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#111111"
borderopacity="1"
inkscape:pageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
inkscape:document-units="px"
showgrid="false"
objecttolerance="1"
gridtolerance="1"
guidetolerance="1"
units="px"
inkscape:zoom="9.8434981"
inkscape:cx="45.664661"
inkscape:cy="15.238485"
inkscape:window-width="2880"
inkscape:window-height="1526"
inkscape:window-x="2869"
inkscape:window-y="-11"
inkscape:window-maximized="1"
inkscape:current-layer="svg5"
inkscape:showpageshadow="0"
inkscape:deskcolor="#505050" />
<defs
id="defs2">
<linearGradient
inkscape:collect="always"
id="linearGradient95">
<stop
style="stop-color:#1794fa;stop-opacity:1;"
offset="0"
id="stop91" />
<stop
style="stop-color:#13bfc6;stop-opacity:1"
offset="1"
id="stop93" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient95"
id="linearGradient293"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.08815381,0,0,0.0881538,11.309701,1.5887868)"
x1="-117.92336"
y1="-11.113196"
x2="-65.095886"
y2="41.619678" />
</defs>
<path
id="path37-4-6-8"
style="fill:url(#linearGradient293);fill-opacity:1;stroke-width:0"
d="M 3.1702654,8.5090788e-7 A 3.1750206,3.1750201 0 0 0 0,3.1749136 3.1750206,3.1750201 0 0 0 3.1749144,6.3499995 3.1750206,3.1750201 0 0 0 5.0929493,5.7050313 L 4.2301789,4.8067917 A 1.9434973,1.9434971 0 0 1 3.1749144,5.1184294 1.9434973,1.9434971 0 0 1 1.2313979,3.1749136 1.9434973,1.9434971 0 0 1 3.1749144,1.2313976 1.9434973,1.9434971 0 0 1 5.1184286,3.1749136 1.9434973,1.9434971 0 0 1 4.7124407,4.3636127 L 5.5712515,5.2577193 A 3.1750206,3.1750201 0 0 0 6.35,3.1749136 3.1750206,3.1750201 0 0 0 3.1749144,8.5090788e-7 a 3.1750206,3.1750201 0 0 0 -0.00465,0 z" />
<metadata
id="metadata7980">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:title>Petal Search logo</dc:title>
<dc:date>16 agt 2021</dc:date>
<cc:license
rdf:resource="http://scripts.sil.org/OFL" />
<dc:language>es</dc:language>
</cc:Work>
<cc:License
rdf:about="http://scripts.sil.org/OFL">
<cc:permits
rdf:resource="http://scripts.sil.org/pub/OFL/Reproduction" />
<cc:permits
rdf:resource="http://scripts.sil.org/pub/OFL/Distribution" />
<cc:permits
rdf:resource="http://scripts.sil.org/pub/OFL/Embedding" />
<cc:permits
rdf:resource="http://scripts.sil.org/pub/OFL/DerivativeWorks" />
<cc:requires
rdf:resource="http://scripts.sil.org/pub/OFL/Notice" />
<cc:requires
rdf:resource="http://scripts.sil.org/pub/OFL/Attribution" />
<cc:requires
rdf:resource="http://scripts.sil.org/pub/OFL/ShareAlike" />
<cc:requires
rdf:resource="http://scripts.sil.org/pub/OFL/DerivativeRenaming" />
<cc:requires
rdf:resource="http://scripts.sil.org/pub/OFL/BundlingWhenSelling" />
</cc:License>
</rdf:RDF>
</metadata>
</svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
img/semrush.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 745 B

56
img/serpstat.svg Normal file
View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="50"
height="50"
viewBox="0 0 50 50"
fill="none"
version="1.1"
id="svg10"
sodipodi:docname="serpstat.svg"
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs10" />
<sodipodi:namedview
id="namedview10"
pagecolor="#505050"
bordercolor="#ffffff"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
inkscape:deskcolor="#505050"
showgrid="false"
inkscape:zoom="12.76917"
inkscape:cx="22.201913"
inkscape:cy="36.024268"
inkscape:window-width="2880"
inkscape:window-height="1526"
inkscape:window-x="2869"
inkscape:window-y="-11"
inkscape:window-maximized="1"
inkscape:current-layer="svg10" />
<circle
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.667;stroke-linecap:round;stroke-linejoin:round"
id="path11"
cx="25"
cy="25"
r="25" />
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M 45.702134,8.3195919 H 17.013253 l 0.0014,0.00698 c -0.489237,0.019502 -0.882289,0.4220257 -0.882289,0.9206576 0,0.2646403 0.111311,0.5000213 0.287168,0.6685583 l -0.0042,0.0042 6.210894,6.2356742 c 0.361415,0.363527 0.361415,0.955483 0.0014,1.319011 l -10.21856,10.269285 c -0.262504,0.266037 -0.199286,0.714514 0.127823,0.892796 L 13.8082,29.33314 c 0.233591,0.128169 0.599277,0.101725 0.827326,-0.03614 0.316152,-0.190867 0.683107,-0.302294 1.077545,-0.302294 0.270772,0 0.526417,0.05577 0.76278,0.15184 0.133366,0.05427 0.284513,0.03764 0.391667,-0.05993 l 2.425861,-2.221484 c -0.0028,-0.04596 -0.01374,-0.09053 -0.01374,-0.137868 0,-1.184007 0.946951,-2.143659 2.115137,-2.143659 0.984133,0 1.80326,0.68253 2.039623,1.60454 l 2.351616,1.011267 c 0.07275,0.0306 0.152533,0.01813 0.218464,-0.02645 0.339476,-0.239595 0.74904,-0.383121 1.193013,-0.383121 0.210267,0 0.413606,0.03487 0.606091,0.0948 0.07147,0.02368 0.148375,0.007 0.203337,-0.04596 l 4.061355,-4.008587 c 0.05912,-0.05716 0.08937,-0.142141 0.08799,-0.224239 -0.03579,-2.106015 1.499463,-2.349768 2.102783,-2.370667 0.915313,-0.03475 1.68502,0.604589 1.969533,1.441615 0.02887,0.07944 0.08787,0.144911 0.167659,0.174125 l 2.572852,0.891411 c 0.09757,0.03475 0.200683,0.007 0.277585,-0.06132 0.373884,-0.342592 0.867278,-0.552974 1.410091,-0.552974 0.192485,0 0.527804,0.122627 0.722944,-0.09192 l 5.104482,-5.271851 c 0.08937,-0.09053 0.138792,-0.213096 0.138792,-0.342628 V 9.2527843 c 7e-6,-0.515345 -0.412328,-0.9331924 -0.920849,-0.9331924 z"
fill="#0c63f6"
id="path9"
style="stroke-width:1.15468" />
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="m 46.609134,20.648544 c 0,-0.277007 -0.332432,-0.415453 -0.523877,-0.21604 l -3.24984,3.351912 c -0.07113,0.07205 -0.09849,0.175973 -0.0821,0.277123 0.08348,0.551243 -0.02737,1.16761 -0.750886,1.846329 -0.381621,0.358759 -0.867164,0.605282 -1.388269,0.592811 -0.849381,-0.02356 -1.564704,-0.559556 -1.876582,-1.311713 -0.03279,-0.07898 -0.09434,-0.143988 -0.176435,-0.173086 l -2.684971,-0.932172 c -0.09295,-0.03186 -0.192831,-0.0083 -0.270772,0.05531 -0.361067,0.296406 -0.819243,0.476536 -1.319911,0.476536 -0.22701,0 -0.441779,-0.04572 -0.646967,-0.113621 0,0 -3.063704,3.001585 -4.15245,4.086058 -0.132672,0.134404 -0.134058,0.144103 -0.104033,0.414182 0,1.177309 -0.940947,2.13165 -2.104976,2.13165 -0.983439,0 -1.804069,-0.684146 -2.035235,-1.606618 -0.02459,-0.09422 -0.08476,-0.174588 -0.173663,-0.213384 l -1.994244,-0.855963 c -0.101145,-0.04572 -0.21477,-0.02356 -0.303679,0.04434 -0.35287,0.27285 -0.790493,0.439008 -1.266451,0.439008 -0.227125,0 -0.445936,-0.03741 -0.651122,-0.106576 -0.121703,-0.04018 -0.254375,-0.0194 -0.350099,0.06639 l -2.426438,2.221831 c -0.0821,0.07471 -0.12586,0.178628 -0.1381,0.289476 -0.106694,1.074774 -0.998565,1.914225 -2.089966,1.914225 -0.845339,0 -1.566089,-0.507019 -1.899906,-1.23562 -0.08753,-0.191099 -0.248833,-0.335088 -0.429424,-0.436237 l -2.731437,-1.493111 c -0.214735,-0.117778 -0.478717,-0.0776 -0.651053,0.09549 l -8.0821233,8.090478 -0.00274,0.0028 -0.010946,0.01109 0.00274,0.0014 c -0.1586565,0.16614 -0.2585034,0.39061 -0.2585034,0.639904 0,0.511061 0.4075942,0.925243 0.9136674,0.925243 H 29.209763 c 0.507365,0 1.217261,-0.29502 1.578329,-0.65655 l 0.519835,-0.522144 0.01502,-0.01524 6.221979,-6.242762 c 0.359682,-0.360144 0.946489,-0.360144 1.306171,0 l 6.204196,6.228906 c 0.166852,0.173087 0.396632,0.28255 0.655164,0.28255 0.503325,0 0.913697,-0.412797 0.913697,-0.922471 z"
fill="#0c63f6"
id="path10"
style="stroke-width:1.15468" />
</svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

59
img/vivaldi.svg Normal file
View File

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="23.999901"
height="23.999901"
viewBox="0 0 23.999901 23.999901"
fill="none"
version="1.1"
id="svg11"
sodipodi:docname="vivaldi.svg"
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview11"
pagecolor="#505050"
bordercolor="#ffffff"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
inkscape:deskcolor="#505050"
inkscape:zoom="19.239437"
inkscape:cx="41.399341"
inkscape:cy="10.759151"
inkscape:window-width="2880"
inkscape:window-height="1526"
inkscape:window-x="2869"
inkscape:window-y="-11"
inkscape:window-maximized="1"
inkscape:current-layer="svg11" />
<path
d="m 11.9999,23.9999 c 5.2586,0 8.1808,0 10.0904,-1.9096 1.9096,-1.9096 1.9096,-4.8318 1.9096,-10.0904 0,-5.25852 0,-8.18075 -1.9096,-10.09033 C 20.1807,0 17.2585,0 11.9999,0 6.74138,0 3.81554,0 1.90958,1.90957 0.00361653,3.81915 0,6.74138 0,11.9999 c 0,5.2586 -1.72454e-7,8.1808 1.90958,10.0904 1.90957,1.9096 4.8318,1.9096 10.09032,1.9096 z"
fill="#ef3939"
id="path8" />
<path
d="M 18.357,5.63297 C 17.0983,4.37517 15.495,3.51886 13.7499,3.17229 12.0047,2.82572 10.196,3.00445 8.55243,3.68589 6.90881,4.36733 5.50407,5.52088 4.51577,7.00073 3.52747,8.48058 2.99999,10.2203 2.99999,11.9999 c 0,1.7797 0.52748,3.5194 1.51578,4.9993 0.9883,1.4798 2.39304,2.6334 4.03666,3.3148 1.64357,0.6814 3.45227,0.8602 5.19747,0.5136 1.7451,-0.3466 3.3484,-1.2029 4.6071,-2.4607 0.8377,-0.8351 1.5024,-1.8274 1.9559,-2.92 0.4535,-1.0926 0.687,-2.2639 0.687,-3.447 0,-1.183 -0.2335,-2.35436 -0.687,-3.44694 C 19.8594,7.46037 19.1947,6.46808 18.357,5.63297 Z m -0.5395,4.14324 c -1.4846,2.58349 -2.9679,5.16579 -4.45,7.74689 -0.1169,0.2288 -0.2911,0.4235 -0.5056,0.565 -0.2144,0.1415 -0.4619,0.2251 -0.7182,0.2426 -0.283,0.0316 -0.5689,-0.023 -0.8203,-0.1568 C 11.0721,18.0401 10.867,17.8334 10.7352,17.581 9.7974,15.9657 8.86685,14.3396 7.9363,12.717 7.36663,11.7319 6.79937,10.7444 6.23452,9.75448 6.10043,9.53221 6.02649,9.27885 6.01996,9.01933 6.01343,8.75981 6.07454,8.50305 6.19728,8.27431 6.32002,8.04557 6.50017,7.85273 6.72001,7.71473 6.93985,7.57674 7.19181,7.49836 7.45111,7.48729 7.73024,7.47017 8.00836,7.53424 8.25187,7.67178 8.49539,7.80931 8.69389,8.01442 8.8234,8.26234 c 0.42001,0.72434 0.83278,1.44868 1.2456,2.17306 0.3005,0.5215 0.5901,1.043 0.8979,1.5573 0.1957,0.3554 0.4798,0.6542 0.8249,0.8675 0.3452,0.2132 0.7395,0.3335 1.1448,0.3494 0.6156,0.0381 1.2222,-0.1621 1.6941,-0.5593 0.4719,-0.3972 0.7728,-0.9607 0.8405,-1.5739 0,-0.0978 0,-0.1956 0.0217,-0.2463 0.0022,-0.3875 -0.0846,-0.7703 -0.2534,-1.11908 -0.1036,-0.1921 -0.1638,-0.40453 -0.1766,-0.6224 -0.0128,-0.21786 0.0223,-0.43588 0.1027,-0.63875 0.0804,-0.20288 0.2043,-0.38569 0.3628,-0.53562 0.1586,-0.14993 0.348,-0.26333 0.555,-0.33227 0.207,-0.06893 0.4266,-0.09172 0.6434,-0.06676 0.2167,0.02496 0.4254,0.09706 0.6113,0.21124 0.186,0.11418 0.3447,0.26768 0.465,0.44972 0.1203,0.18204 0.1994,0.38822 0.2316,0.60406 0.0408,0.34694 -0.0357,0.69755 -0.2172,0.99597 z"
fill="#ffffff"
id="path10" />
<defs
id="defs11">
<linearGradient
id="paint0_linear"
x1="7.4818001"
y1="4.2225299"
x2="18.940599"
y2="24.0763"
gradientUnits="userSpaceOnUse">
<stop
stop-opacity="0.2"
id="stop10" />
<stop
offset="0.79"
stop-opacity="0.05"
id="stop11" />
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

8
php_errors.log Normal file
View File

@@ -0,0 +1,8 @@
[03-Sep-2025 15:22:41 UTC] PHP Warning: Undefined variable $file in D:\Webroot\development\lib\plugins\botmon\cleanup.php on line 14
[03-Sep-2025 15:22:54 UTC] PHP Warning: Undefined variable $file in D:\Webroot\development\lib\plugins\botmon\cleanup.php on line 14
[03-Sep-2025 15:25:36 UTC] PHP Parse error: syntax error, unexpected end of file, expecting "," or ";" in D:\Webroot\development\lib\plugins\botmon\cleanup.php on line 15
[03-Sep-2025 15:35:57 UTC] PHP Deprecated: Using ${var} in strings is deprecated, use {$var} instead in D:\Webroot\development\lib\plugins\botmon\cleanup.php on line 14
[03-Sep-2025 15:37:51 UTC] PHP Warning: unlink(logs/.): Is a directory in D:\Webroot\development\lib\plugins\botmon\cleanup.php on line 15
[03-Sep-2025 15:37:51 UTC] PHP Warning: unlink(logs/..): Resource temporarily unavailable in D:\Webroot\development\lib\plugins\botmon\cleanup.php on line 15
[03-Sep-2025 15:38:10 UTC] PHP Warning: unlink(logs/.): Is a directory in D:\Webroot\development\lib\plugins\botmon\cleanup.php on line 17
[03-Sep-2025 15:38:10 UTC] PHP Warning: unlink(logs/..): Resource temporarily unavailable in D:\Webroot\development\lib\plugins\botmon\cleanup.php on line 17

257
script.js
View File

@@ -3,6 +3,16 @@
/* 04.09.2025 - 0.1.8 - pre-release */
/* Authors: Sascha Leib <ad@hominem.info> */
// enumeration of user types:
const BM_USERTYPE = Object.freeze({
'UNKNOWN': 'unknown',
'KNOWN_USER': 'user',
'HUMAN': 'human',
'LIKELY_BOT': 'likely_bot',
'KNOWN_BOT': 'known_bot'
});
/* BotMon root object */
const BotMon = {
init: function() {
@@ -179,7 +189,9 @@ BotMon.live = {
_visitors: [],
// find an already existing visitor record:
findVisitor: function(id) {
findVisitor: function(visitor) {
//console.info('BotMon.live.data.model.findVisitor()');
//console.log(visitor);
// shortcut to make code more readable:
const model = BotMon.live.data.model;
@@ -187,7 +199,29 @@ BotMon.live = {
// loop over all visitors already registered:
for (let i=0; i<model._visitors.length; i++) {
const v = model._visitors[i];
if (v && v.id == id) return v;
if (visitor._type == BM_USERTYPE.KNOWN_BOT) { /* known bots */
// bots match when their ID matches:
if (v._bot && v._bot.id == visitor._bot.id) {
return v;
}
} else if (visitor._type == BM_USERTYPE.KNOWN_USER) { /* registered users */
// visitors match when their names match:
if ( v.usr == visitor.usr
&& v.ip == visitor.ip
&& v.agent == visitor.agent) {
return v;
}
} else { /* any other visitor */
if ( v.id == visitor.id) { /* match the pre-defined IDs */
return v;
}
}
}
return null; // nothing found
},
@@ -210,56 +244,47 @@ BotMon.live = {
},
// register a new visitor (or update if already exists)
registerVisit: function(dat, type) {
console.info('registerVisit', dat);
registerVisit: function(nv, type) {
//console.info('registerVisit', nv, type);
// shortcut to make code more readable:
const model = BotMon.live.data.model;
// is it a known bot?
const bot = BotMon.live.data.bots.match(dat.agent);
const bot = BotMon.live.data.bots.match(nv.agent);
// which user id to use:
let visitorId = dat.id; // default is the session ID
if (bot) visitorId = bot.id; // use bot ID if known bot
if (dat.usr !== '') visitorId = 'usr'; // use user ID if known user
// enrich new visitor with relevant data:
if (!nv._bot) nv._bot = bot ?? null; // bot info
nv._type = ( bot ? BM_USERTYPE.KNOWN_BOT : ( nv.usr !== '' ? BM_USERTYPE.KNOWN_USER : BM_USERTYPE.UNKNOWN ) );
if (!nv._firstSeen) nv._firstSeen = nv.ts;
if (!nv._lastSeen) nv._lastSeen = nv.ts;
// check if it already exists:
let visitor = model.findVisitor(dat.id);
let visitor = model.findVisitor(nv);
if (!visitor) {
// override the visitor type?
let visitorType = dat.typ;
if (bot) visitorType = 'bot';
model._visitors.push(dat);
visitor = dat;
visitor.id = visitorId;
visitor._firstSeen = dat.ts;
visitor._lastSeen = dat.ts;
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(dat.agent) ?? null; // client info
visitor._bot = bot ?? null; // bot info
visitor._platform = BotMon.live.data.platforms.match(dat.agent); // platform info
visitor._type = visitorType;
visitor._client = BotMon.live.data.clients.match(nv.agent) ?? null; // client info
visitor._platform = BotMon.live.data.platforms.match(nv.agent); // platform info
model._visitors.push(visitor);
}
// find browser
// is this visit already registered?
let prereg = model._getVisit(visitor, dat);
let prereg = model._getVisit(visitor, nv);
if (!prereg) {
// add the page view to the visitor:
prereg = {
_by: 'srv',
ip: dat.ip,
pg: dat.pg,
ref: dat.ref || '',
_firstSeen: dat.ts,
_lastSeen: dat.ts,
ip: nv.ip,
pg: nv.pg,
ref: nv.ref || '',
_firstSeen: nv.ts,
_lastSeen: nv.ts,
_jsClient: false
};
visitor._pageViews.push(prereg);
@@ -270,7 +295,7 @@ BotMon.live = {
(prereg.ref !== undefined && prereg.ref !== '');
// update time stamp for last-seen:
visitor._lastSeen = dat.ts;
visitor._lastSeen = nv.ts;
// if needed:
return visitor;
@@ -279,13 +304,14 @@ BotMon.live = {
// updating visit data from the client-side log:
updateVisit: function(dat) {
//console.info('updateVisit', dat);
return;
// shortcut to make code more readable:
const model = BotMon.live.data.model;
const type = 'log';
let visitor = BotMon.live.data.model.findVisitor(dat.id);
let visitor = BotMon.live.data.model.findVisitor(dat);
if (!visitor) {
visitor = model.registerVisit(dat, type);
visitor._seenBy = [type];
@@ -324,14 +350,15 @@ BotMon.live = {
// updating visit data from the ticker log:
updateTicks: function(dat) {
//console.info('updateTicks', dat);
return;
// shortcut to make code more readable:
const model = BotMon.live.data.model;
// find the visit info:
let visitor = model.findVisitor(dat.id);
let visitor = model.findVisitor(dat);
if (!visitor) {
console.warn(`No visitor with ID ${dat.id}, registering a new one.`);
//console.warn(`No visitor with ID ${dat.id}, registering a new one.`);
visitor = model.registerVisit(dat, 'tck');
}
if (visitor) {
@@ -345,7 +372,7 @@ BotMon.live = {
// update the page view info:
if (pv._lastSeen.getTime() < dat.ts.getTime()) pv._lastSeen = dat.ts;
} else {
console.warn(`No page view for visit ID ${dat.id}, page ${dat.pg}, registering a new one.`);
//console.warn(`No page view for visit ID ${dat.id}, page ${dat.pg}, registering a new one.`);
// add a new page view to the visitor:
const newPv = {
@@ -359,19 +386,14 @@ BotMon.live = {
};
visitor._pageViews.push(newPv);
}
} else {
console.warn(`No visit with ID ${dat.id}.`);
return;
}
}
}
},
analytics: {
init: function() {
console.info('BotMon.live.data.analytics.init()');
//console.info('BotMon.live.data.analytics.init()');
},
// data storage:
@@ -412,49 +434,27 @@ BotMon.live = {
// check for typical bot aspects:
let botScore = 0;
/*if (v._isBot >= 1.0) { // known bots
if (v._type == BM_USERTYPE.KNOWN_BOT) { // known bots
this.data.bots.known += 1;
this.groups.knownBots.push(v);
} if (v.usr && v.usr != '') { // known users */
} else if (v._type == BM_USERTYPE.KNOWN_USER) { // known users */
this.groups.users.push(v);
this.data.bots.users += 1;
/*} else {
// not a known bot, nor a known user; check other aspects:
} else {
// no referrer at all:
if (!v._hasReferrer) botScore += 0.2;
// no js client logging:
if (!v._jsClient) botScore += 0.2;
// average time between page views less than 30s:
if (v._pageViews.length > 1) {
botScore -= 0.2; // more than one view: good!
let totalDiff = 0;
for (let i=1; i<v._pageViews.length; i++) {
const diff = v._pageViews[i]._firstSeen.getTime() - v._pageViews[i-1]._lastSeen.getTime();
totalDiff += diff;
}
const avgDiff = totalDiff / (v._pageViews.length - 1);
if (avgDiff < 30000) botScore += 0.2;
else if (avgDiff < 60000) botScore += 0.1;
}
// decide based on the score:
if (botScore >= 0.5) {
this.data.bots.suspected += 1;
this.groups.suspectedBots.push(v);
} else {
this.data.bots.human += 1;
this.groups.humans.push(v);
}
}*/
// TODO: find suspected bots
this.data.bots.suspected += 1;
this.groups.suspectedBots.push(v);
}
});
console.log(this.data);
console.log(this.groups);
//console.log(this.data);
//console.log(this.groups);
}
},
@@ -736,8 +736,13 @@ BotMon.live = {
overview: {
make: function() {
const data = BotMon.live.data.analytics.data;
const parent = document.getElementById('botmon__today__content');
// shortcut for neater code:
const makeElement = BotMon.t._makeElement;
if (parent) {
const bounceRate = Math.round(data.totalVisits / data.totalPageViews * 1000) / 10;
@@ -760,15 +765,29 @@ BotMon.live = {
<dd><span>Probably humans:</span><span>${data.bots.human}</span></dd>
<dd><span>Registered users:</span><span>${data.bots.users}</span></dd>
</dl>
<dl id="botmon__botslist">
<dt>Known bots</dt>
</dl>
<dl id="botmon__botslist"></dl>
</div>
</details>
`));
// update known bots list:
const block = document.getElementById('botmon__botslist');
block.innerHTML = "<dt>Top known bots</dt>";
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, 4); i++) {
const dd = makeElement('dd');
dd.appendChild(makeElement('span', {'class': 'bot bot_' + bots[i]._bot.id}, bots[i]._bot.n));
dd.appendChild(makeElement('span', undefined, bots[i]._pageViews.length));
block.appendChild(dd);
}
}
}
},
status: {
setText: function(txt) {
const el = document.getElementById('botmon__today__status');
@@ -864,7 +883,7 @@ BotMon.live = {
},
_onDetailsToggle: function(e) {
console.info('BotMon.live.gui.lists._onDetailsToggle()');
//console.info('BotMon.live.gui.lists._onDetailsToggle()');
const target = e.target;
@@ -904,17 +923,20 @@ BotMon.live = {
const span1 = make('span'); /* left-hand group */
if (data._type == 'bot') { /* Bot only */
const platformName = (data._platform ? data._platform.n : 'Unknown');
const clientName = (data._client ? data._client.n: 'Unknown');
if (data._type == BM_USERTYPE.KNOWN_BOT) { /* Bot only */
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')));
} else if (data._type == 'usr') { /* User only */
} else if (data._type == BM_USERTYPE.KNOWN_USER) { /* User only */
span1.appendChild(make('span', { /* User */
'class': 'user' + (data._user ? data._user.id : 'unknown'),
'class': 'user_known',
'title': "User: " + data.usr
}, data.usr));
@@ -928,27 +950,24 @@ BotMon.live = {
}
const platformName = (data._platform ? data._platform.n : 'Unknown');
span1.appendChild(make('span', { /* Platform */
'class': 'icon platform platform_' + (data._platform ? data._platform.id : 'unknown'),
'title': "Platform: " + platformName
}, platformName));
if (data._type !== BM_USERTYPE.KNOWN_BOT) { /* Not for bots */
span1.appendChild(make('span', { /* Platform */
'class': 'icon platform platform_' + (data._platform ? data._platform.id : 'unknown'),
'title': "Platform: " + platformName
}, platformName));
const clientName = (data._client ? data._client.n: 'Unknown');
span1.appendChild(make('span', { /* Client */
'class': 'icon client client_' + (data._client ? data._client.id : 'unknown'),
'title': "Client: " + clientName
}, clientName));
span1.appendChild(make('span', { /* Client */
'class': 'icon client client_' + (data._client ? data._client.id : 'unknown'),
'title': "Client: " + clientName
}, clientName));
}
summary.appendChild(span1);
const span2 = make('span'); /* right-hand group */
span2.appendChild(make('time', { /* Last seen */
'data-field': 'last-seen',
'datetime': (data._lastSeen ? data._lastSeen : 'unknown')
}, (data._lastSeen ? data._lastSeen.getHours() + ':' + data._lastSeen.getMinutes() + ':' + data._lastSeen.getSeconds() : 'Unknown')));
span2.appendChild(make('span', { /* page views */
'class': 'pageviews'
}, data._pageViews.length));
summary.appendChild(span2);
@@ -956,20 +975,33 @@ BotMon.live = {
const dl = make('dl', {'class': 'visitor_details'});
if (data._bot) {
dl.appendChild(make('dt', {}, "Bot:")); /* bot info */
if (data._type == BM_USERTYPE.KNOWN_BOT) {
dl.appendChild(make('dt', {}, "Bot name:")); /* bot info */
dl.appendChild(make('dd', {'class': 'has_icon bot bot_' + (data._bot ? data._bot.id : 'unknown')},
(data._bot ? data._bot.n : 'Unknown')));
if (data._bot && data._bot.url) {
dl.appendChild(make('dt', {}, "Bot info:")); /* bot info */
const botInfoDd = dl.appendChild(make('dd'));
botInfoDd.appendChild(make('a', {
'href': data._bot.url,
'target': '_blank'
}, data._bot.url)); /* bot info link*/
}
} else { /* not for bots */
dl.appendChild(make('dt', {}, "Client:")); /* client */
dl.appendChild(make('dd', {'class': 'has_icon client_' + (data._client ? data._client.id : 'unknown')},
clientName + ( data._client.v > 0 ? ' (' + data._client.v + ')' : '' ) ));
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', {}, "Client:")); /* client */
dl.appendChild(make('dd', {'class': 'has_icon client_' + (data._client ? data._client.id : 'unknown')},
clientName + ( data._client.v > 0 ? ' (' + data._client.v + ')' : '' ) ));
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));
@@ -986,6 +1018,12 @@ BotMon.live = {
dl.appendChild(make('dt', {}, "User-Agent:"));
dl.appendChild(make('dd', {'class': 'agent' + ipType}, data.agent));
dl.appendChild(make('dt', {}, "Visitor Type:"));
dl.appendChild(make('dd', undefined, data._type ));
dl.appendChild(make('dt', {}, "Seen by:"));
dl.appendChild(make('dd', undefined, data._seenBy.join(', ') ));
dl.appendChild(make('dt', {}, "Visited pages:"));
const pagesDd = make('dd', {'class': 'pages'});
const pageList = make('ul');
@@ -1013,6 +1051,7 @@ BotMon.live = {
li.appendChild(details);
return li;
}
}
}
};

View File

@@ -129,7 +129,8 @@
color: #000;
}
details ul > li > details {
border: red dotted 1px;
border: #ccc solid 1px;
border-radius: .5em;
}
details ul > li > details > summary {
display: flex;
@@ -139,24 +140,30 @@
font-weight: normal;
font-size: 1rem;
line-height: 1.5;
border: blue dashed 1px;
background-color: #F0F0F0;
border-bottom: #CCC solid 1px;
border-radius: .5em;
}
details ul > li > details > summary > span {
display: flex;
align-items: center;
column-gap: .25em;
}
details ul > li > details > summary > span:first-child {
flex-grow: 1;
}
details ul > li > details > summary > span > span {
display: flex;
align-items: center;
column-gap: .25em;
height: 1.5em;
overflow: hidden;
}
details ul > li > details > summary > span > span::before {
content: '';
display: inline-block;
width: 1.25em; height: 1em;
min-width: 1.25em; height: 1em;
text-align: center;
background: transparent url('img/placeholder.svg') center no-repeat;
background-size: 1em;
@@ -171,9 +178,9 @@
dl.visitor_details {
& {
border: green dotted 1px;
display: grid;
grid-template-columns: min-content auto;
border-left: transparent none 0;
}
dt {
grid-column: 1;
@@ -184,6 +191,19 @@
display: inline-block;
background-color: transparent;
}
dd.pages {
& {
}
ul {
li {
& {
display: flex;
justify-content: space-between;
align-items: center;
}
}
}
}
}
dd.has_icon::before {
content: '';
@@ -200,12 +220,13 @@
span.bot_googleads::before, dd.bot_googleads::before,
span.bot_googleapi::before, dd.bot_googleapi::before { background-image: url('img/google.svg') }
span.bot_applebot::before, dd.bot_applebot::before { background-image: url('img/apple.svg') }
span.bot_openai::before, dd.bot_openai::before { background-image: url('img/openai.svg') }
span.bot_metabots::before, dd.bot_metabots::before { background-image: url('img/meta.svg') }
span.bot_yandexbots::before, dd.bot_yandexbots::before { background-image: url('img/yandex.svg') }
span.bot_seznambot::before, dd.bot_seznambot::before { background-image: url('img/seznam.svg') }
/* user info */
span.user::before { background-image: url('img/user.svg') }
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') }
@@ -217,6 +238,7 @@
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') }
span.platform_bsd::before, dd.platform_bsd::before { background-image: url('img/freebsd.png') }
/* browser icons */
span.client_opera::before, dd.client_opera::before { background-image: url('img/opera.svg') }
@@ -231,6 +253,7 @@
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') }
/* ip address type */
span.ip6::before, dd.ip6::before { background-image: url('img/ip6.svg') }
@@ -240,6 +263,15 @@
/* user agent */
span.agent::before { background-image: url('img/info.svg') }
/* pageviews */
span.pageviews {
border: #999 solid 1px;
padding: 0 2px;
font-size: smaller;
border-radius: .25em;
}
span.pageviews::before { background-image: url('img/page.svg') }
}
/* item footer */