@naturalcycles/js-lib 14.255.0 → 14.256.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bot.d.ts +60 -0
- package/dist/bot.js +129 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist-esm/bot.js +125 -0
- package/dist-esm/index.js +1 -0
- package/package.json +1 -1
- package/src/bot.ts +155 -0
- package/src/index.ts +1 -0
package/dist/bot.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export interface BotDetectionServiceCfg {
|
|
2
|
+
/**
|
|
3
|
+
* Defaults to false.
|
|
4
|
+
* If true - the instance will memoize (remember) the results of the detection
|
|
5
|
+
* and won't re-run it.
|
|
6
|
+
*/
|
|
7
|
+
memoizeResults?: boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Defaults to false.
|
|
10
|
+
* If set to true: `getBotReason()` would return BotReason.CDP if CDP is detected.
|
|
11
|
+
* Otherwise - `getBotReason()` will not perform the CDP check.
|
|
12
|
+
*/
|
|
13
|
+
treatCDPAsBotReason?: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Service to detect bots and CDP (Chrome DevTools Protocol).
|
|
17
|
+
*
|
|
18
|
+
* @experimental
|
|
19
|
+
*/
|
|
20
|
+
export declare class BotDetectionService {
|
|
21
|
+
cfg: BotDetectionServiceCfg;
|
|
22
|
+
constructor(cfg?: BotDetectionServiceCfg);
|
|
23
|
+
private botReason;
|
|
24
|
+
private cdp;
|
|
25
|
+
isBotOrCDP(): boolean;
|
|
26
|
+
isBot(): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Returns null if it's not a Bot,
|
|
29
|
+
* otherwise a truthy BotReason.
|
|
30
|
+
*/
|
|
31
|
+
getBotReason(): BotReason | null;
|
|
32
|
+
private detectBotReason;
|
|
33
|
+
/**
|
|
34
|
+
* CDP stands for Chrome DevTools Protocol.
|
|
35
|
+
* This function tests if the current environment is a CDP environment.
|
|
36
|
+
* If it's true - it's one of:
|
|
37
|
+
*
|
|
38
|
+
* 1. Bot, automated with CDP, e.g Puppeteer, Playwright or such.
|
|
39
|
+
* 2. Developer with Chrome DevTools open.
|
|
40
|
+
*
|
|
41
|
+
* 2 is certainly not a bot, but unfortunately we can't distinguish between the two.
|
|
42
|
+
* That's why this function is not part of `isBot()`, because it can give "false positive" with DevTools.
|
|
43
|
+
*
|
|
44
|
+
* Based on: https://deviceandbrowserinfo.com/learning_zone/articles/detecting-headless-chrome-puppeteer-2024
|
|
45
|
+
*/
|
|
46
|
+
isCDP(): boolean;
|
|
47
|
+
private detectCDP;
|
|
48
|
+
}
|
|
49
|
+
export declare enum BotReason {
|
|
50
|
+
NoNavigator = 1,
|
|
51
|
+
NoUserAgent = 2,
|
|
52
|
+
UserAgent = 3,
|
|
53
|
+
WebDriver = 4,
|
|
54
|
+
EmptyLanguages = 6,
|
|
55
|
+
/**
|
|
56
|
+
* This is when CDP is considered to be a reason to be a Bot.
|
|
57
|
+
* By default it's not.
|
|
58
|
+
*/
|
|
59
|
+
CDP = 8
|
|
60
|
+
}
|
package/dist/bot.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Relevant material:
|
|
3
|
+
// https://deviceandbrowserinfo.com/learning_zone/articles/detecting-headless-chrome-puppeteer-2024
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.BotReason = exports.BotDetectionService = void 0;
|
|
6
|
+
const env_1 = require("./env");
|
|
7
|
+
/**
|
|
8
|
+
* Service to detect bots and CDP (Chrome DevTools Protocol).
|
|
9
|
+
*
|
|
10
|
+
* @experimental
|
|
11
|
+
*/
|
|
12
|
+
class BotDetectionService {
|
|
13
|
+
constructor(cfg = {}) {
|
|
14
|
+
this.cfg = cfg;
|
|
15
|
+
}
|
|
16
|
+
isBotOrCDP() {
|
|
17
|
+
return !!this.getBotReason() || this.isCDP();
|
|
18
|
+
}
|
|
19
|
+
isBot() {
|
|
20
|
+
return !!this.getBotReason();
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Returns null if it's not a Bot,
|
|
24
|
+
* otherwise a truthy BotReason.
|
|
25
|
+
*/
|
|
26
|
+
getBotReason() {
|
|
27
|
+
if (this.cfg.memoizeResults && this.botReason !== undefined) {
|
|
28
|
+
return this.botReason;
|
|
29
|
+
}
|
|
30
|
+
this.botReason = this.detectBotReason();
|
|
31
|
+
return this.botReason;
|
|
32
|
+
}
|
|
33
|
+
detectBotReason() {
|
|
34
|
+
// SSR - not a bot
|
|
35
|
+
if ((0, env_1.isServerSide)())
|
|
36
|
+
return null;
|
|
37
|
+
const { navigator } = globalThis;
|
|
38
|
+
if (!navigator)
|
|
39
|
+
return BotReason.NoNavigator;
|
|
40
|
+
const { userAgent } = navigator;
|
|
41
|
+
if (!userAgent)
|
|
42
|
+
return BotReason.NoUserAgent;
|
|
43
|
+
if (/bot|headless|electron|phantom|slimer/i.test(userAgent)) {
|
|
44
|
+
return BotReason.UserAgent;
|
|
45
|
+
}
|
|
46
|
+
if (navigator.webdriver) {
|
|
47
|
+
return BotReason.WebDriver;
|
|
48
|
+
}
|
|
49
|
+
// Kirill: commented out, as it's no longer seems reliable,
|
|
50
|
+
// e.g generates false positives with latest Android clients (e.g. Chrome 129)
|
|
51
|
+
// if (navigator.plugins?.length === 0) {
|
|
52
|
+
// return BotReason.ZeroPlugins // Headless Chrome
|
|
53
|
+
// }
|
|
54
|
+
if (navigator.languages === '') {
|
|
55
|
+
return BotReason.EmptyLanguages; // Headless Chrome
|
|
56
|
+
}
|
|
57
|
+
// isChrome is true if the browser is Chrome, Chromium or Opera
|
|
58
|
+
// this is "the chrome test" from https://intoli.com/blog/not-possible-to-block-chrome-headless/
|
|
59
|
+
// this property is for some reason not present by default in headless chrome
|
|
60
|
+
// Kirill: criterium removed due to false positives with Android
|
|
61
|
+
// if (userAgent.includes('Chrome') && !(globalThis as any).chrome) {
|
|
62
|
+
// return BotReason.ChromeWithoutChrome // Headless Chrome
|
|
63
|
+
// }
|
|
64
|
+
if (this.cfg.treatCDPAsBotReason && this.detectCDP()) {
|
|
65
|
+
return BotReason.CDP;
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* CDP stands for Chrome DevTools Protocol.
|
|
71
|
+
* This function tests if the current environment is a CDP environment.
|
|
72
|
+
* If it's true - it's one of:
|
|
73
|
+
*
|
|
74
|
+
* 1. Bot, automated with CDP, e.g Puppeteer, Playwright or such.
|
|
75
|
+
* 2. Developer with Chrome DevTools open.
|
|
76
|
+
*
|
|
77
|
+
* 2 is certainly not a bot, but unfortunately we can't distinguish between the two.
|
|
78
|
+
* That's why this function is not part of `isBot()`, because it can give "false positive" with DevTools.
|
|
79
|
+
*
|
|
80
|
+
* Based on: https://deviceandbrowserinfo.com/learning_zone/articles/detecting-headless-chrome-puppeteer-2024
|
|
81
|
+
*/
|
|
82
|
+
isCDP() {
|
|
83
|
+
if (this.cfg.memoizeResults && this.cdp !== undefined) {
|
|
84
|
+
return this.cdp;
|
|
85
|
+
}
|
|
86
|
+
this.cdp = this.detectCDP();
|
|
87
|
+
return this.cdp;
|
|
88
|
+
}
|
|
89
|
+
detectCDP() {
|
|
90
|
+
if ((0, env_1.isServerSide)())
|
|
91
|
+
return false;
|
|
92
|
+
let cdpCheck1 = false;
|
|
93
|
+
try {
|
|
94
|
+
/* eslint-disable */
|
|
95
|
+
// biome-ignore lint/suspicious/useErrorMessage: ok
|
|
96
|
+
const e = new window.Error();
|
|
97
|
+
window.Object.defineProperty(e, 'stack', {
|
|
98
|
+
configurable: false,
|
|
99
|
+
enumerable: false,
|
|
100
|
+
// biome-ignore lint/complexity/useArrowFunction: ok
|
|
101
|
+
get: function () {
|
|
102
|
+
cdpCheck1 = true;
|
|
103
|
+
return '';
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
// This is part of the detection and shouldn't be deleted
|
|
107
|
+
window.console.debug(e);
|
|
108
|
+
/* eslint-enable */
|
|
109
|
+
}
|
|
110
|
+
catch { }
|
|
111
|
+
return cdpCheck1;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
exports.BotDetectionService = BotDetectionService;
|
|
115
|
+
var BotReason;
|
|
116
|
+
(function (BotReason) {
|
|
117
|
+
BotReason[BotReason["NoNavigator"] = 1] = "NoNavigator";
|
|
118
|
+
BotReason[BotReason["NoUserAgent"] = 2] = "NoUserAgent";
|
|
119
|
+
BotReason[BotReason["UserAgent"] = 3] = "UserAgent";
|
|
120
|
+
BotReason[BotReason["WebDriver"] = 4] = "WebDriver";
|
|
121
|
+
// ZeroPlugins = 5,
|
|
122
|
+
BotReason[BotReason["EmptyLanguages"] = 6] = "EmptyLanguages";
|
|
123
|
+
// ChromeWithoutChrome = 7,
|
|
124
|
+
/**
|
|
125
|
+
* This is when CDP is considered to be a reason to be a Bot.
|
|
126
|
+
* By default it's not.
|
|
127
|
+
*/
|
|
128
|
+
BotReason[BotReason["CDP"] = 8] = "CDP";
|
|
129
|
+
})(BotReason || (exports.BotReason = BotReason = {}));
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ const tslib_1 = require("tslib");
|
|
|
5
5
|
tslib_1.__exportStar(require("./abort"), exports);
|
|
6
6
|
tslib_1.__exportStar(require("./array/array.util"), exports);
|
|
7
7
|
tslib_1.__exportStar(require("./array/range"), exports);
|
|
8
|
+
tslib_1.__exportStar(require("./bot"), exports);
|
|
8
9
|
tslib_1.__exportStar(require("./datetime/dateInterval"), exports);
|
|
9
10
|
tslib_1.__exportStar(require("./datetime/localDate"), exports);
|
|
10
11
|
tslib_1.__exportStar(require("./datetime/localTime"), exports);
|
package/dist-esm/bot.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// Relevant material:
|
|
2
|
+
// https://deviceandbrowserinfo.com/learning_zone/articles/detecting-headless-chrome-puppeteer-2024
|
|
3
|
+
import { isServerSide } from './env';
|
|
4
|
+
/**
|
|
5
|
+
* Service to detect bots and CDP (Chrome DevTools Protocol).
|
|
6
|
+
*
|
|
7
|
+
* @experimental
|
|
8
|
+
*/
|
|
9
|
+
export class BotDetectionService {
|
|
10
|
+
constructor(cfg = {}) {
|
|
11
|
+
this.cfg = cfg;
|
|
12
|
+
}
|
|
13
|
+
isBotOrCDP() {
|
|
14
|
+
return !!this.getBotReason() || this.isCDP();
|
|
15
|
+
}
|
|
16
|
+
isBot() {
|
|
17
|
+
return !!this.getBotReason();
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Returns null if it's not a Bot,
|
|
21
|
+
* otherwise a truthy BotReason.
|
|
22
|
+
*/
|
|
23
|
+
getBotReason() {
|
|
24
|
+
if (this.cfg.memoizeResults && this.botReason !== undefined) {
|
|
25
|
+
return this.botReason;
|
|
26
|
+
}
|
|
27
|
+
this.botReason = this.detectBotReason();
|
|
28
|
+
return this.botReason;
|
|
29
|
+
}
|
|
30
|
+
detectBotReason() {
|
|
31
|
+
// SSR - not a bot
|
|
32
|
+
if (isServerSide())
|
|
33
|
+
return null;
|
|
34
|
+
const { navigator } = globalThis;
|
|
35
|
+
if (!navigator)
|
|
36
|
+
return BotReason.NoNavigator;
|
|
37
|
+
const { userAgent } = navigator;
|
|
38
|
+
if (!userAgent)
|
|
39
|
+
return BotReason.NoUserAgent;
|
|
40
|
+
if (/bot|headless|electron|phantom|slimer/i.test(userAgent)) {
|
|
41
|
+
return BotReason.UserAgent;
|
|
42
|
+
}
|
|
43
|
+
if (navigator.webdriver) {
|
|
44
|
+
return BotReason.WebDriver;
|
|
45
|
+
}
|
|
46
|
+
// Kirill: commented out, as it's no longer seems reliable,
|
|
47
|
+
// e.g generates false positives with latest Android clients (e.g. Chrome 129)
|
|
48
|
+
// if (navigator.plugins?.length === 0) {
|
|
49
|
+
// return BotReason.ZeroPlugins // Headless Chrome
|
|
50
|
+
// }
|
|
51
|
+
if (navigator.languages === '') {
|
|
52
|
+
return BotReason.EmptyLanguages; // Headless Chrome
|
|
53
|
+
}
|
|
54
|
+
// isChrome is true if the browser is Chrome, Chromium or Opera
|
|
55
|
+
// this is "the chrome test" from https://intoli.com/blog/not-possible-to-block-chrome-headless/
|
|
56
|
+
// this property is for some reason not present by default in headless chrome
|
|
57
|
+
// Kirill: criterium removed due to false positives with Android
|
|
58
|
+
// if (userAgent.includes('Chrome') && !(globalThis as any).chrome) {
|
|
59
|
+
// return BotReason.ChromeWithoutChrome // Headless Chrome
|
|
60
|
+
// }
|
|
61
|
+
if (this.cfg.treatCDPAsBotReason && this.detectCDP()) {
|
|
62
|
+
return BotReason.CDP;
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* CDP stands for Chrome DevTools Protocol.
|
|
68
|
+
* This function tests if the current environment is a CDP environment.
|
|
69
|
+
* If it's true - it's one of:
|
|
70
|
+
*
|
|
71
|
+
* 1. Bot, automated with CDP, e.g Puppeteer, Playwright or such.
|
|
72
|
+
* 2. Developer with Chrome DevTools open.
|
|
73
|
+
*
|
|
74
|
+
* 2 is certainly not a bot, but unfortunately we can't distinguish between the two.
|
|
75
|
+
* That's why this function is not part of `isBot()`, because it can give "false positive" with DevTools.
|
|
76
|
+
*
|
|
77
|
+
* Based on: https://deviceandbrowserinfo.com/learning_zone/articles/detecting-headless-chrome-puppeteer-2024
|
|
78
|
+
*/
|
|
79
|
+
isCDP() {
|
|
80
|
+
if (this.cfg.memoizeResults && this.cdp !== undefined) {
|
|
81
|
+
return this.cdp;
|
|
82
|
+
}
|
|
83
|
+
this.cdp = this.detectCDP();
|
|
84
|
+
return this.cdp;
|
|
85
|
+
}
|
|
86
|
+
detectCDP() {
|
|
87
|
+
if (isServerSide())
|
|
88
|
+
return false;
|
|
89
|
+
let cdpCheck1 = false;
|
|
90
|
+
try {
|
|
91
|
+
/* eslint-disable */
|
|
92
|
+
// biome-ignore lint/suspicious/useErrorMessage: ok
|
|
93
|
+
const e = new window.Error();
|
|
94
|
+
window.Object.defineProperty(e, 'stack', {
|
|
95
|
+
configurable: false,
|
|
96
|
+
enumerable: false,
|
|
97
|
+
// biome-ignore lint/complexity/useArrowFunction: ok
|
|
98
|
+
get: function () {
|
|
99
|
+
cdpCheck1 = true;
|
|
100
|
+
return '';
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
// This is part of the detection and shouldn't be deleted
|
|
104
|
+
window.console.debug(e);
|
|
105
|
+
/* eslint-enable */
|
|
106
|
+
}
|
|
107
|
+
catch { }
|
|
108
|
+
return cdpCheck1;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
export var BotReason;
|
|
112
|
+
(function (BotReason) {
|
|
113
|
+
BotReason[BotReason["NoNavigator"] = 1] = "NoNavigator";
|
|
114
|
+
BotReason[BotReason["NoUserAgent"] = 2] = "NoUserAgent";
|
|
115
|
+
BotReason[BotReason["UserAgent"] = 3] = "UserAgent";
|
|
116
|
+
BotReason[BotReason["WebDriver"] = 4] = "WebDriver";
|
|
117
|
+
// ZeroPlugins = 5,
|
|
118
|
+
BotReason[BotReason["EmptyLanguages"] = 6] = "EmptyLanguages";
|
|
119
|
+
// ChromeWithoutChrome = 7,
|
|
120
|
+
/**
|
|
121
|
+
* This is when CDP is considered to be a reason to be a Bot.
|
|
122
|
+
* By default it's not.
|
|
123
|
+
*/
|
|
124
|
+
BotReason[BotReason["CDP"] = 8] = "CDP";
|
|
125
|
+
})(BotReason || (BotReason = {}));
|
package/dist-esm/index.js
CHANGED
package/package.json
CHANGED
package/src/bot.ts
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
// Relevant material:
|
|
2
|
+
// https://deviceandbrowserinfo.com/learning_zone/articles/detecting-headless-chrome-puppeteer-2024
|
|
3
|
+
|
|
4
|
+
import { isServerSide } from './env'
|
|
5
|
+
|
|
6
|
+
export interface BotDetectionServiceCfg {
|
|
7
|
+
/**
|
|
8
|
+
* Defaults to false.
|
|
9
|
+
* If true - the instance will memoize (remember) the results of the detection
|
|
10
|
+
* and won't re-run it.
|
|
11
|
+
*/
|
|
12
|
+
memoizeResults?: boolean
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Defaults to false.
|
|
16
|
+
* If set to true: `getBotReason()` would return BotReason.CDP if CDP is detected.
|
|
17
|
+
* Otherwise - `getBotReason()` will not perform the CDP check.
|
|
18
|
+
*/
|
|
19
|
+
treatCDPAsBotReason?: boolean
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Service to detect bots and CDP (Chrome DevTools Protocol).
|
|
24
|
+
*
|
|
25
|
+
* @experimental
|
|
26
|
+
*/
|
|
27
|
+
export class BotDetectionService {
|
|
28
|
+
constructor(public cfg: BotDetectionServiceCfg = {}) {}
|
|
29
|
+
|
|
30
|
+
// memoized results
|
|
31
|
+
private botReason: BotReason | null | undefined
|
|
32
|
+
private cdp: boolean | undefined
|
|
33
|
+
|
|
34
|
+
isBotOrCDP(): boolean {
|
|
35
|
+
return !!this.getBotReason() || this.isCDP()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
isBot(): boolean {
|
|
39
|
+
return !!this.getBotReason()
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Returns null if it's not a Bot,
|
|
44
|
+
* otherwise a truthy BotReason.
|
|
45
|
+
*/
|
|
46
|
+
getBotReason(): BotReason | null {
|
|
47
|
+
if (this.cfg.memoizeResults && this.botReason !== undefined) {
|
|
48
|
+
return this.botReason
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
this.botReason = this.detectBotReason()
|
|
52
|
+
return this.botReason
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private detectBotReason(): BotReason | null {
|
|
56
|
+
// SSR - not a bot
|
|
57
|
+
if (isServerSide()) return null
|
|
58
|
+
const { navigator } = globalThis
|
|
59
|
+
if (!navigator) return BotReason.NoNavigator
|
|
60
|
+
const { userAgent } = navigator
|
|
61
|
+
if (!userAgent) return BotReason.NoUserAgent
|
|
62
|
+
|
|
63
|
+
if (/bot|headless|electron|phantom|slimer/i.test(userAgent)) {
|
|
64
|
+
return BotReason.UserAgent
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (navigator.webdriver) {
|
|
68
|
+
return BotReason.WebDriver
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Kirill: commented out, as it's no longer seems reliable,
|
|
72
|
+
// e.g generates false positives with latest Android clients (e.g. Chrome 129)
|
|
73
|
+
// if (navigator.plugins?.length === 0) {
|
|
74
|
+
// return BotReason.ZeroPlugins // Headless Chrome
|
|
75
|
+
// }
|
|
76
|
+
|
|
77
|
+
if ((navigator.languages as any) === '') {
|
|
78
|
+
return BotReason.EmptyLanguages // Headless Chrome
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// isChrome is true if the browser is Chrome, Chromium or Opera
|
|
82
|
+
// this is "the chrome test" from https://intoli.com/blog/not-possible-to-block-chrome-headless/
|
|
83
|
+
// this property is for some reason not present by default in headless chrome
|
|
84
|
+
// Kirill: criterium removed due to false positives with Android
|
|
85
|
+
// if (userAgent.includes('Chrome') && !(globalThis as any).chrome) {
|
|
86
|
+
// return BotReason.ChromeWithoutChrome // Headless Chrome
|
|
87
|
+
// }
|
|
88
|
+
|
|
89
|
+
if (this.cfg.treatCDPAsBotReason && this.detectCDP()) {
|
|
90
|
+
return BotReason.CDP
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return null
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* CDP stands for Chrome DevTools Protocol.
|
|
98
|
+
* This function tests if the current environment is a CDP environment.
|
|
99
|
+
* If it's true - it's one of:
|
|
100
|
+
*
|
|
101
|
+
* 1. Bot, automated with CDP, e.g Puppeteer, Playwright or such.
|
|
102
|
+
* 2. Developer with Chrome DevTools open.
|
|
103
|
+
*
|
|
104
|
+
* 2 is certainly not a bot, but unfortunately we can't distinguish between the two.
|
|
105
|
+
* That's why this function is not part of `isBot()`, because it can give "false positive" with DevTools.
|
|
106
|
+
*
|
|
107
|
+
* Based on: https://deviceandbrowserinfo.com/learning_zone/articles/detecting-headless-chrome-puppeteer-2024
|
|
108
|
+
*/
|
|
109
|
+
isCDP(): boolean {
|
|
110
|
+
if (this.cfg.memoizeResults && this.cdp !== undefined) {
|
|
111
|
+
return this.cdp
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
this.cdp = this.detectCDP()
|
|
115
|
+
return this.cdp
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private detectCDP(): boolean {
|
|
119
|
+
if (isServerSide()) return false
|
|
120
|
+
let cdpCheck1 = false
|
|
121
|
+
try {
|
|
122
|
+
/* eslint-disable */
|
|
123
|
+
// biome-ignore lint/suspicious/useErrorMessage: ok
|
|
124
|
+
const e = new window.Error()
|
|
125
|
+
window.Object.defineProperty(e, 'stack', {
|
|
126
|
+
configurable: false,
|
|
127
|
+
enumerable: false,
|
|
128
|
+
// biome-ignore lint/complexity/useArrowFunction: ok
|
|
129
|
+
get: function () {
|
|
130
|
+
cdpCheck1 = true
|
|
131
|
+
return ''
|
|
132
|
+
},
|
|
133
|
+
})
|
|
134
|
+
// This is part of the detection and shouldn't be deleted
|
|
135
|
+
window.console.debug(e)
|
|
136
|
+
/* eslint-enable */
|
|
137
|
+
} catch {}
|
|
138
|
+
return cdpCheck1
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export enum BotReason {
|
|
143
|
+
NoNavigator = 1,
|
|
144
|
+
NoUserAgent = 2,
|
|
145
|
+
UserAgent = 3,
|
|
146
|
+
WebDriver = 4,
|
|
147
|
+
// ZeroPlugins = 5,
|
|
148
|
+
EmptyLanguages = 6,
|
|
149
|
+
// ChromeWithoutChrome = 7,
|
|
150
|
+
/**
|
|
151
|
+
* This is when CDP is considered to be a reason to be a Bot.
|
|
152
|
+
* By default it's not.
|
|
153
|
+
*/
|
|
154
|
+
CDP = 8,
|
|
155
|
+
}
|