ua-browser 1.4.0-beta.1 → 1.4.1
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/README.en.md +41 -0
- package/README.md +58 -1
- package/dist/index.cjs +305 -126
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -3
- package/dist/index.d.ts +29 -3
- package/dist/index.min.js +2 -2
- package/dist/index.min.js.map +1 -1
- package/dist/index.mjs +305 -127
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -4,7 +4,79 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
// package.json
|
|
6
6
|
var package_default = {
|
|
7
|
-
version: "1.4.
|
|
7
|
+
version: "1.4.1"};
|
|
8
|
+
|
|
9
|
+
// src/constants/os.ts
|
|
10
|
+
var OS_DEFS = [
|
|
11
|
+
{ name: "WebOS", priority: 20, detect: /hpwOS/, versionPattern: /hpwOS\/([\d.]+)/ },
|
|
12
|
+
{ name: "Symbian", priority: 20, detect: /Symbian/, versionPattern: null },
|
|
13
|
+
{ name: "MeeGo", priority: 20, detect: /MeeGo/, versionPattern: null },
|
|
14
|
+
{ name: "BlackBerry", priority: 20, detect: /(BlackBerry|RIM)/, versionPattern: null },
|
|
15
|
+
{ name: "FreeBSD", priority: 20, detect: /FreeBSD/, versionPattern: null },
|
|
16
|
+
{ name: "Debian", priority: 20, detect: /Debian/, versionPattern: /Debian\/([\d.]+)/ },
|
|
17
|
+
{ name: "Ubuntu", priority: 20, detect: /Ubuntu/, versionPattern: null },
|
|
18
|
+
{ name: "Linux", priority: 10, detect: /(Linux|X11)/, versionPattern: null },
|
|
19
|
+
{ name: "Chrome OS", priority: 30, detect: /CrOS/, versionPattern: null },
|
|
20
|
+
{ name: "Tizen", priority: 20, detect: /Tizen/, versionPattern: /Tizen ([\d.]+)/ },
|
|
21
|
+
{ name: "iOS", priority: 20, detect: /like Mac OS X/, versionPattern: /OS ([\d_]+) like/ },
|
|
22
|
+
{
|
|
23
|
+
name: "MacOS",
|
|
24
|
+
priority: 20,
|
|
25
|
+
detect: /Macintosh/,
|
|
26
|
+
versionPattern: /Mac OS X -?([\d_.]+)/,
|
|
27
|
+
versionNames: {
|
|
28
|
+
"10.9": "Mavericks",
|
|
29
|
+
"10.10": "Yosemite",
|
|
30
|
+
"10.11": "El Capitan",
|
|
31
|
+
"10.12": "Sierra",
|
|
32
|
+
"10.13": "High Sierra",
|
|
33
|
+
"10.14": "Mojave",
|
|
34
|
+
"10.15": "Catalina",
|
|
35
|
+
"11": "Big Sur",
|
|
36
|
+
"12": "Monterey",
|
|
37
|
+
"13": "Ventura",
|
|
38
|
+
"14": "Sonoma",
|
|
39
|
+
"15": "Sequoia"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{ name: "visionOS", priority: 30, detect: /visionOS/, versionPattern: /visionOS ([\d_]+)/ },
|
|
43
|
+
{ name: "tvOS", priority: 30, detect: /Apple TV/, versionPattern: /OS ([\d_]+) like/ },
|
|
44
|
+
{ name: "Android", priority: 20, detect: /(Android|Adr)/, versionPattern: /(?:Android|Adr) ([\d.]+)/ },
|
|
45
|
+
{
|
|
46
|
+
name: "HarmonyOS",
|
|
47
|
+
priority: 30,
|
|
48
|
+
detect: /HarmonyOS/,
|
|
49
|
+
versionPattern: [/HarmonyOS[\s/]([\d.]+)/, /Android ([\d.]+)[;)]/],
|
|
50
|
+
versionLookup: { "10": "2", "11": "3", "12": "3", "13": "4", "14": "4" }
|
|
51
|
+
},
|
|
52
|
+
{ name: "OpenHarmony", priority: 30, detect: /OpenHarmony/, versionPattern: /OpenHarmony[\s/]([\d.]+)/ },
|
|
53
|
+
{ name: "KaiOS", priority: 30, detect: /KAIOS/, versionPattern: /KAIOS\/([\d.]+)/ },
|
|
54
|
+
{
|
|
55
|
+
name: "Windows",
|
|
56
|
+
priority: 10,
|
|
57
|
+
detect: /Windows/,
|
|
58
|
+
versionPattern: /Windows NT ([\d.]+)/,
|
|
59
|
+
versionLookup: {
|
|
60
|
+
"10": "10",
|
|
61
|
+
"6.4": "10",
|
|
62
|
+
"6.3": "8.1",
|
|
63
|
+
"6.2": "8",
|
|
64
|
+
"6.1": "7",
|
|
65
|
+
"6.0": "Vista",
|
|
66
|
+
"5.2": "XP",
|
|
67
|
+
"5.1": "XP",
|
|
68
|
+
"5.0": "2000"
|
|
69
|
+
},
|
|
70
|
+
versionNames: {
|
|
71
|
+
"7": "Windows 7",
|
|
72
|
+
"8": "Windows 8",
|
|
73
|
+
"8.1": "Windows 8.1",
|
|
74
|
+
"10": "Windows 10",
|
|
75
|
+
"11": "Windows 11"
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
{ name: "Windows Phone", priority: 30, detect: /(IEMobile|Windows Phone)/, versionPattern: /Windows Phone(?: OS)? ([\d.]+)/ }
|
|
79
|
+
];
|
|
8
80
|
|
|
9
81
|
// src/constants/browsers.ts
|
|
10
82
|
var BROWSER_DEFS = [
|
|
@@ -151,7 +223,7 @@ function detectBrowser(ua) {
|
|
|
151
223
|
}
|
|
152
224
|
}
|
|
153
225
|
}
|
|
154
|
-
if (!best) return { browser: "unknown", version: "unknown" };
|
|
226
|
+
if (!best) return { browser: "unknown", version: "unknown", browserType: "unknown", priority: 0 };
|
|
155
227
|
let version = null;
|
|
156
228
|
if (best.chromeLookup) {
|
|
157
229
|
version = lookupFromChromeVersion(ua, best.chromeLookup);
|
|
@@ -160,7 +232,9 @@ function detectBrowser(ua) {
|
|
|
160
232
|
const patterns = Array.isArray(best.versionPattern) ? best.versionPattern : [best.versionPattern];
|
|
161
233
|
version = extractVersionFromPatterns(ua, patterns);
|
|
162
234
|
}
|
|
163
|
-
|
|
235
|
+
const p = best.priority;
|
|
236
|
+
const browserType = p >= 500 ? "app" : p >= 300 ? "brand" : "browser";
|
|
237
|
+
return { browser: best.name, version: version != null ? version : "unknown", browserType, priority: p };
|
|
164
238
|
}
|
|
165
239
|
|
|
166
240
|
// src/constants/engines.ts
|
|
@@ -176,8 +250,17 @@ var ENGINE_DEFS = [
|
|
|
176
250
|
];
|
|
177
251
|
|
|
178
252
|
// src/detectors/engine.ts
|
|
253
|
+
var ENGINE_VERSION_RE = {
|
|
254
|
+
WebKit: /AppleWebKit\/([\d.]+)/,
|
|
255
|
+
Blink: /AppleWebKit\/([\d.]+)/,
|
|
256
|
+
ArkWeb: /AppleWebKit\/([\d.]+)/,
|
|
257
|
+
Gecko: /Gecko\/([\d.]+)/,
|
|
258
|
+
Trident: /Trident\/([\d.]+)/,
|
|
259
|
+
Presto: /Presto\/([\d.]+)/,
|
|
260
|
+
KHTML: /KHTML\/([\d.]+)/
|
|
261
|
+
};
|
|
179
262
|
function detectEngine(ua, browser, version) {
|
|
180
|
-
var _a, _b;
|
|
263
|
+
var _a, _b, _c, _d;
|
|
181
264
|
if (browser === void 0 || version === void 0) {
|
|
182
265
|
const b = detectBrowser(ua);
|
|
183
266
|
browser = browser != null ? browser : b.browser;
|
|
@@ -199,72 +282,29 @@ function detectEngine(ua, browser, version) {
|
|
|
199
282
|
if (browser === "Edge") {
|
|
200
283
|
engine = parseInt(version, 10) > 75 ? "Blink" : "EdgeHTML";
|
|
201
284
|
}
|
|
202
|
-
|
|
285
|
+
const engineVersion = ENGINE_VERSION_RE[engine] ? (_d = (_c = ENGINE_VERSION_RE[engine].exec(ua)) == null ? void 0 : _c[1]) != null ? _d : "unknown" : "unknown";
|
|
286
|
+
return { engine, engineVersion };
|
|
203
287
|
}
|
|
204
288
|
|
|
205
|
-
// src/constants/os.ts
|
|
206
|
-
var OS_DEFS = [
|
|
207
|
-
{ name: "WebOS", detect: /hpwOS/, versionPattern: /hpwOS\/([\d.]+)/ },
|
|
208
|
-
{ name: "Symbian", detect: /Symbian/, versionPattern: null },
|
|
209
|
-
{ name: "MeeGo", detect: /MeeGo/, versionPattern: null },
|
|
210
|
-
{ name: "BlackBerry", detect: /(BlackBerry|RIM)/, versionPattern: null },
|
|
211
|
-
{ name: "FreeBSD", detect: /FreeBSD/, versionPattern: null },
|
|
212
|
-
{ name: "Debian", detect: /Debian/, versionPattern: /Debian\/([\d.]+)/ },
|
|
213
|
-
{ name: "Ubuntu", detect: /Ubuntu/, versionPattern: null },
|
|
214
|
-
// Linux must come before Chrome OS: Chrome OS UAs contain "X11", so Linux matches first,
|
|
215
|
-
// then Chrome OS overrides it.
|
|
216
|
-
{ name: "Linux", detect: /(Linux|X11)/, versionPattern: null },
|
|
217
|
-
{ name: "Chrome OS", detect: /CrOS/, versionPattern: null },
|
|
218
|
-
{ name: "Tizen", detect: /Tizen/, versionPattern: /Tizen ([\d.]+)/ },
|
|
219
|
-
{ name: "iOS", detect: /like Mac OS X/, versionPattern: /OS ([\d_]+) like/ },
|
|
220
|
-
{ name: "MacOS", detect: /Macintosh/, versionPattern: /Mac OS X -?([\d_.]+)/ },
|
|
221
|
-
// visionOS / tvOS must come AFTER iOS: their UAs also contain "like Mac OS X",
|
|
222
|
-
// so they need to override iOS via the last-match-wins iteration.
|
|
223
|
-
{ name: "visionOS", detect: /visionOS/, versionPattern: /visionOS ([\d_]+)/ },
|
|
224
|
-
{ name: "tvOS", detect: /Apple TV/, versionPattern: /OS ([\d_]+) like/ },
|
|
225
|
-
{ name: "Android", detect: /(Android|Adr)/, versionPattern: /(?:Android|Adr) ([\d.]+)/ },
|
|
226
|
-
// HarmonyOS must come after Android: HarmonyOS UAs include "Android", so Android matches
|
|
227
|
-
// first, then HarmonyOS overrides it. versionPattern tries direct extraction first (5.0+
|
|
228
|
-
// pure HarmonyOS UAs don't have Android token), then falls back to Android version + lookup.
|
|
229
|
-
{
|
|
230
|
-
name: "HarmonyOS",
|
|
231
|
-
detect: /HarmonyOS/,
|
|
232
|
-
versionPattern: [/HarmonyOS[\s/]([\d.]+)/, /Android ([\d.]+)[;)]/],
|
|
233
|
-
versionLookup: { "10": "2", "11": "3", "12": "3", "13": "4" }
|
|
234
|
-
},
|
|
235
|
-
// OpenHarmony (open-source base) must come after HarmonyOS to override any earlier match.
|
|
236
|
-
{ name: "OpenHarmony", detect: /OpenHarmony/, versionPattern: /OpenHarmony[\s/]([\d.]+)/ },
|
|
237
|
-
{ name: "KaiOS", detect: /KAIOS/, versionPattern: /KAIOS\/([\d.]+)/ },
|
|
238
|
-
// Windows must come before Windows Phone: Windows Phone UAs contain "Windows", so Windows
|
|
239
|
-
// matches first, then Windows Phone overrides it.
|
|
240
|
-
{
|
|
241
|
-
name: "Windows",
|
|
242
|
-
detect: /Windows/,
|
|
243
|
-
versionPattern: /Windows NT ([\d.]+)/,
|
|
244
|
-
versionLookup: {
|
|
245
|
-
"10": "10",
|
|
246
|
-
"6.4": "10",
|
|
247
|
-
"6.3": "8.1",
|
|
248
|
-
"6.2": "8",
|
|
249
|
-
"6.1": "7",
|
|
250
|
-
"6.0": "Vista",
|
|
251
|
-
"5.2": "XP",
|
|
252
|
-
"5.1": "XP",
|
|
253
|
-
"5.0": "2000"
|
|
254
|
-
}
|
|
255
|
-
},
|
|
256
|
-
{ name: "Windows Phone", detect: /(IEMobile|Windows Phone)/, versionPattern: /Windows Phone(?: OS)? ([\d.]+)/ }
|
|
257
|
-
];
|
|
258
|
-
|
|
259
289
|
// src/detectors/os.ts
|
|
290
|
+
function lookupVersionName(map, version) {
|
|
291
|
+
const parts = version.split(".");
|
|
292
|
+
for (let len = parts.length; len >= 1; len--) {
|
|
293
|
+
const key = parts.slice(0, len).join(".");
|
|
294
|
+
if (Object.prototype.hasOwnProperty.call(map, key)) return map[key];
|
|
295
|
+
}
|
|
296
|
+
return "unknown";
|
|
297
|
+
}
|
|
260
298
|
function detectOs(ua, windowsVersion) {
|
|
261
299
|
let matchedDef = null;
|
|
300
|
+
let bestPriority = -1;
|
|
262
301
|
for (const def of OS_DEFS) {
|
|
263
|
-
if (def.detect.test(ua)) {
|
|
302
|
+
if (def.detect.test(ua) && def.priority > bestPriority) {
|
|
264
303
|
matchedDef = def;
|
|
304
|
+
bestPriority = def.priority;
|
|
265
305
|
}
|
|
266
306
|
}
|
|
267
|
-
if (!matchedDef) return { os: "unknown", osVersion: "unknown" };
|
|
307
|
+
if (!matchedDef) return { os: "unknown", osVersion: "unknown", osVersionName: "unknown" };
|
|
268
308
|
let osVersion = "unknown";
|
|
269
309
|
if (matchedDef.versionPattern) {
|
|
270
310
|
const raw = Array.isArray(matchedDef.versionPattern) ? extractVersionFromPatterns(ua, matchedDef.versionPattern) : extractVersion(ua, matchedDef.versionPattern);
|
|
@@ -288,7 +328,8 @@ function detectOs(ua, windowsVersion) {
|
|
|
288
328
|
if (matchedDef.name === "Windows" && windowsVersion) {
|
|
289
329
|
osVersion = windowsVersion;
|
|
290
330
|
}
|
|
291
|
-
|
|
331
|
+
const osVersionName = matchedDef.versionNames ? lookupVersionName(matchedDef.versionNames, osVersion) : "unknown";
|
|
332
|
+
return { os: matchedDef.name, osVersion, osVersionName };
|
|
292
333
|
}
|
|
293
334
|
|
|
294
335
|
// src/constants/devices.ts
|
|
@@ -353,57 +394,93 @@ function detectDevice(ua, nav) {
|
|
|
353
394
|
}
|
|
354
395
|
return (_b = (_a = hwDetect()) != null ? _a : uaDetect()) != null ? _b : "PC";
|
|
355
396
|
}
|
|
397
|
+
var VENDOR_MAP = [
|
|
398
|
+
[/^SM-|^GT-|^SGH-|^SCH-|^SHW-|^SPH-|^SAMSUNG /i, "Samsung"],
|
|
399
|
+
[/^Pixel |^Nexus /, "Google"],
|
|
400
|
+
[/^moto |^motorola /i, "Motorola"],
|
|
401
|
+
[/^HONOR /i, "Honor"],
|
|
402
|
+
[/^ELS-|^LYA-|^HMA-|^VOG-|^ANA-|^CLT-|^JNY-|^NOH-|^PLK-|^BAH-|^BKL-|^COL-|^DUB-|^FIG-|^KIW-|^MAR-|^VTR-|^WAS-/i, "Huawei"],
|
|
403
|
+
[/^CPH/, "OPPO"],
|
|
404
|
+
[/^RMX/, "Realme"],
|
|
405
|
+
[/^V\d{4}[A-Z]|^vivo /i, "Vivo"],
|
|
406
|
+
[/^iqoo/i, "Vivo"],
|
|
407
|
+
[/^Redmi |^POCO |^Mi /, "Xiaomi"],
|
|
408
|
+
[/^2\d{9}|^2\d{3}[A-Z]/, "Xiaomi"],
|
|
409
|
+
[/^OnePlus |^IN2|^KB2|^LE2/i, "OnePlus"],
|
|
410
|
+
[/^LM-|^LGE |^LG-/i, "LG"],
|
|
411
|
+
[/^HTC/i, "HTC"],
|
|
412
|
+
[/^Nokia/i, "Nokia"],
|
|
413
|
+
[/^XQ-/, "Sony"],
|
|
414
|
+
[/^ASUS_|^ZB6|^ZS6|^ZE[56]/i, "Asus"],
|
|
415
|
+
[/^Quest /i, "Meta"]
|
|
416
|
+
];
|
|
417
|
+
var ANDROID_MODEL_RE = /Android [0-9.]+;(?:\s*U;)?(?:\s*[a-z]{2}[-_][a-zA-Z]{2,4};)?\s*([^;)]+?)(?:\s+Build\/|[;)])/;
|
|
418
|
+
function detectVendorModel(ua) {
|
|
419
|
+
if (/visionOS/.test(ua)) return { vendor: "Apple", model: "Apple Vision Pro" };
|
|
420
|
+
if (/iPhone/.test(ua)) return { vendor: "Apple", model: "iPhone" };
|
|
421
|
+
if (/iPad/.test(ua)) return { vendor: "Apple", model: "iPad" };
|
|
422
|
+
if (/iPod/.test(ua)) return { vendor: "Apple", model: "iPod touch" };
|
|
423
|
+
const m = ANDROID_MODEL_RE.exec(ua);
|
|
424
|
+
if (m) {
|
|
425
|
+
const model = m[1].trim();
|
|
426
|
+
for (const [re, vendor] of VENDOR_MAP) {
|
|
427
|
+
if (re.test(model)) return { vendor, model };
|
|
428
|
+
}
|
|
429
|
+
return { vendor: "unknown", model };
|
|
430
|
+
}
|
|
431
|
+
return { vendor: "unknown", model: "unknown" };
|
|
432
|
+
}
|
|
356
433
|
|
|
357
434
|
// src/constants/bots.ts
|
|
358
435
|
var BOT_DEFS = [
|
|
359
436
|
// Search engines
|
|
360
|
-
{ name: "Googlebot", detect: /Googlebot
|
|
361
|
-
{ name: "Bingbot", detect: /(bingbot|BingPreview)
|
|
362
|
-
{ name: "Baiduspider", detect: /(Baiduspider|BaiduMobaider)
|
|
363
|
-
{ name: "Bytespider", detect: /Bytespider
|
|
364
|
-
{ name: "YandexBot", detect: /YandexBot
|
|
365
|
-
{ name: "DuckDuckBot", detect: /DuckDuckBot
|
|
366
|
-
{ name: "Slurp", detect: /Slurp
|
|
367
|
-
{ name: "Sogou", detect: /(Sogou|sogou).*[Ss]pider
|
|
368
|
-
{ name: "360Spider", detect: /360Spider
|
|
369
|
-
{ name: "PetalBot", detect: /PetalBot
|
|
370
|
-
{ name: "Applebot-Extended", detect: /Applebot-Extended
|
|
371
|
-
{ name: "Applebot", detect: /Applebot
|
|
437
|
+
{ name: "Googlebot", detect: /Googlebot/, category: "search-engine" },
|
|
438
|
+
{ name: "Bingbot", detect: /(bingbot|BingPreview)/, category: "search-engine" },
|
|
439
|
+
{ name: "Baiduspider", detect: /(Baiduspider|BaiduMobaider)/, category: "search-engine" },
|
|
440
|
+
{ name: "Bytespider", detect: /Bytespider/, category: "search-engine" },
|
|
441
|
+
{ name: "YandexBot", detect: /YandexBot/, category: "search-engine" },
|
|
442
|
+
{ name: "DuckDuckBot", detect: /DuckDuckBot/, category: "search-engine" },
|
|
443
|
+
{ name: "Slurp", detect: /Slurp/, category: "search-engine" },
|
|
444
|
+
{ name: "Sogou", detect: /(Sogou|sogou).*[Ss]pider/, category: "search-engine" },
|
|
445
|
+
{ name: "360Spider", detect: /360Spider/, category: "search-engine" },
|
|
446
|
+
{ name: "PetalBot", detect: /PetalBot/, category: "search-engine" },
|
|
447
|
+
{ name: "Applebot-Extended", detect: /Applebot-Extended/, category: "search-engine" },
|
|
448
|
+
{ name: "Applebot", detect: /Applebot/, category: "search-engine" },
|
|
372
449
|
// Social media crawlers
|
|
373
|
-
{ name: "Facebookbot", detect: /(facebookexternalhit|FacebookBot)
|
|
374
|
-
{ name: "Twitterbot", detect: /Twitterbot
|
|
375
|
-
{ name: "LinkedInBot", detect: /LinkedInBot
|
|
376
|
-
{ name: "PinterestBot", detect: /
|
|
450
|
+
{ name: "Facebookbot", detect: /(facebookexternalhit|FacebookBot)/, category: "social" },
|
|
451
|
+
{ name: "Twitterbot", detect: /Twitterbot/, category: "social" },
|
|
452
|
+
{ name: "LinkedInBot", detect: /LinkedInBot/, category: "social" },
|
|
453
|
+
{ name: "PinterestBot", detect: /Pinterestbot/i, category: "social" },
|
|
377
454
|
// Messaging link preview bots
|
|
378
|
-
{ name: "Slackbot", detect: /Slackbot
|
|
379
|
-
{ name: "Discordbot", detect: /Discordbot
|
|
380
|
-
{ name: "TelegramBot", detect: /TelegramBot
|
|
381
|
-
{ name: "WhatsApp", detect: /WhatsApp
|
|
455
|
+
{ name: "Slackbot", detect: /Slackbot/, category: "link-preview" },
|
|
456
|
+
{ name: "Discordbot", detect: /Discordbot/, category: "link-preview" },
|
|
457
|
+
{ name: "TelegramBot", detect: /TelegramBot/, category: "link-preview" },
|
|
458
|
+
{ name: "WhatsApp", detect: /WhatsApp/, category: "link-preview" },
|
|
382
459
|
// SEO tools
|
|
383
|
-
{ name: "SemrushBot", detect: /SemrushBot
|
|
384
|
-
{ name: "AhrefsBot", detect: /AhrefsBot
|
|
385
|
-
{ name: "MJ12bot", detect: /MJ12bot
|
|
386
|
-
{ name: "ScreamingFrog", detect: /Screaming Frog
|
|
387
|
-
{ name: "DataForSeoBot", detect: /DataForSeoBot
|
|
460
|
+
{ name: "SemrushBot", detect: /SemrushBot/, category: "seo-tool" },
|
|
461
|
+
{ name: "AhrefsBot", detect: /AhrefsBot/, category: "seo-tool" },
|
|
462
|
+
{ name: "MJ12bot", detect: /MJ12bot/, category: "seo-tool" },
|
|
463
|
+
{ name: "ScreamingFrog", detect: /Screaming Frog/, category: "seo-tool" },
|
|
464
|
+
{ name: "DataForSeoBot", detect: /DataForSeoBot/, category: "seo-tool" },
|
|
388
465
|
// AI / LLM crawlers
|
|
389
|
-
{ name: "GPTBot", detect: /GPTBot
|
|
390
|
-
{ name: "OAI-SearchBot", detect: /OAI-SearchBot
|
|
391
|
-
{ name: "ChatGPT-User", detect: /ChatGPT-User
|
|
392
|
-
{ name: "ClaudeBot", detect: /ClaudeBot
|
|
393
|
-
{ name: "PerplexityBot", detect: /PerplexityBot
|
|
394
|
-
{ name: "CCBot", detect: /CCBot
|
|
395
|
-
{ name: "AdsBot", detect: /AdsBot-Google
|
|
396
|
-
{ name: "Google-Extended", detect: /Google-Extended
|
|
397
|
-
{ name: "Meta-ExternalAgent", detect: /meta-externalagent/i },
|
|
398
|
-
{ name: "Amazonbot", detect: /Amazonbot
|
|
399
|
-
{ name: "Diffbot", detect: /Diffbot
|
|
400
|
-
{ name: "cohere-ai", detect: /cohere-ai
|
|
401
|
-
{ name: "YouBot", detect: /YouBot
|
|
466
|
+
{ name: "GPTBot", detect: /GPTBot/, category: "ai-llm" },
|
|
467
|
+
{ name: "OAI-SearchBot", detect: /OAI-SearchBot/, category: "ai-llm" },
|
|
468
|
+
{ name: "ChatGPT-User", detect: /ChatGPT-User/, category: "ai-llm" },
|
|
469
|
+
{ name: "ClaudeBot", detect: /ClaudeBot/, category: "ai-llm" },
|
|
470
|
+
{ name: "PerplexityBot", detect: /PerplexityBot/, category: "ai-llm" },
|
|
471
|
+
{ name: "CCBot", detect: /CCBot/, category: "ai-llm" },
|
|
472
|
+
{ name: "AdsBot", detect: /AdsBot-Google/, category: "ai-llm" },
|
|
473
|
+
{ name: "Google-Extended", detect: /Google-Extended/, category: "ai-llm" },
|
|
474
|
+
{ name: "Meta-ExternalAgent", detect: /meta-externalagent/i, category: "ai-llm" },
|
|
475
|
+
{ name: "Amazonbot", detect: /Amazonbot/, category: "ai-llm" },
|
|
476
|
+
{ name: "Diffbot", detect: /Diffbot/, category: "ai-llm" },
|
|
477
|
+
{ name: "cohere-ai", detect: /cohere-ai/, category: "ai-llm" },
|
|
478
|
+
{ name: "YouBot", detect: /YouBot/, category: "ai-llm" },
|
|
402
479
|
// Monitoring / archiving
|
|
403
|
-
{ name: "UptimeRobot", detect: /UptimeRobot
|
|
404
|
-
{ name: "ia_archiver", detect: /ia_archiver
|
|
480
|
+
{ name: "UptimeRobot", detect: /UptimeRobot/, category: "monitoring" },
|
|
481
|
+
{ name: "ia_archiver", detect: /ia_archiver/, category: "monitoring" },
|
|
405
482
|
// Generic catch-all (must be last)
|
|
406
|
-
{ name: "GenericBot", detect: /(bot|crawler|spider|crawling|scraper)/i }
|
|
483
|
+
{ name: "GenericBot", detect: /(bot|crawler|spider|crawling|scraper)/i, category: "generic" }
|
|
407
484
|
];
|
|
408
485
|
|
|
409
486
|
// src/detectors/bot.ts
|
|
@@ -411,10 +488,10 @@ function detectBot(ua, customDefs) {
|
|
|
411
488
|
const defs = customDefs ? [...BOT_DEFS.slice(0, -1), ...customDefs, BOT_DEFS[BOT_DEFS.length - 1]] : BOT_DEFS;
|
|
412
489
|
for (const def of defs) {
|
|
413
490
|
if (def.detect.test(ua)) {
|
|
414
|
-
return { isBot: true, botName: def.name };
|
|
491
|
+
return { isBot: true, botName: def.name, botCategory: def.category };
|
|
415
492
|
}
|
|
416
493
|
}
|
|
417
|
-
return { isBot: false, botName: "unknown" };
|
|
494
|
+
return { isBot: false, botName: "unknown", botCategory: "unknown" };
|
|
418
495
|
}
|
|
419
496
|
|
|
420
497
|
// src/constants/arch.ts
|
|
@@ -502,6 +579,7 @@ var BRAND_TO_BROWSER = [
|
|
|
502
579
|
["Microsoft Edge", "Edge"],
|
|
503
580
|
["Opera", "Opera"],
|
|
504
581
|
["Vivaldi", "Vivaldi"],
|
|
582
|
+
["Brave", "Brave"],
|
|
505
583
|
["Google Chrome", "Chrome"],
|
|
506
584
|
["Chromium", "Chromium"]
|
|
507
585
|
];
|
|
@@ -566,6 +644,82 @@ function normalizeBCP47(raw) {
|
|
|
566
644
|
return p.toUpperCase();
|
|
567
645
|
}).join("-");
|
|
568
646
|
}
|
|
647
|
+
var ISO_639_1 = /* @__PURE__ */ new Set([
|
|
648
|
+
"af",
|
|
649
|
+
"am",
|
|
650
|
+
"ar",
|
|
651
|
+
"az",
|
|
652
|
+
"be",
|
|
653
|
+
"bg",
|
|
654
|
+
"bn",
|
|
655
|
+
"bs",
|
|
656
|
+
"ca",
|
|
657
|
+
"cs",
|
|
658
|
+
"cy",
|
|
659
|
+
"da",
|
|
660
|
+
"de",
|
|
661
|
+
"el",
|
|
662
|
+
"en",
|
|
663
|
+
"es",
|
|
664
|
+
"et",
|
|
665
|
+
"eu",
|
|
666
|
+
"fa",
|
|
667
|
+
"fi",
|
|
668
|
+
"fr",
|
|
669
|
+
"ga",
|
|
670
|
+
"gl",
|
|
671
|
+
"gu",
|
|
672
|
+
"he",
|
|
673
|
+
"hi",
|
|
674
|
+
"hr",
|
|
675
|
+
"hu",
|
|
676
|
+
"hy",
|
|
677
|
+
"id",
|
|
678
|
+
"is",
|
|
679
|
+
"it",
|
|
680
|
+
"ja",
|
|
681
|
+
"ka",
|
|
682
|
+
"kk",
|
|
683
|
+
"km",
|
|
684
|
+
"kn",
|
|
685
|
+
"ko",
|
|
686
|
+
"lt",
|
|
687
|
+
"lv",
|
|
688
|
+
"mk",
|
|
689
|
+
"ml",
|
|
690
|
+
"mn",
|
|
691
|
+
"mr",
|
|
692
|
+
"ms",
|
|
693
|
+
"mt",
|
|
694
|
+
"my",
|
|
695
|
+
"nb",
|
|
696
|
+
"ne",
|
|
697
|
+
"nl",
|
|
698
|
+
"no",
|
|
699
|
+
"pa",
|
|
700
|
+
"pl",
|
|
701
|
+
"pt",
|
|
702
|
+
"ro",
|
|
703
|
+
"ru",
|
|
704
|
+
"si",
|
|
705
|
+
"sk",
|
|
706
|
+
"sl",
|
|
707
|
+
"sq",
|
|
708
|
+
"sr",
|
|
709
|
+
"sv",
|
|
710
|
+
"sw",
|
|
711
|
+
"ta",
|
|
712
|
+
"te",
|
|
713
|
+
"th",
|
|
714
|
+
"tl",
|
|
715
|
+
"tr",
|
|
716
|
+
"uk",
|
|
717
|
+
"ur",
|
|
718
|
+
"uz",
|
|
719
|
+
"vi",
|
|
720
|
+
"zh",
|
|
721
|
+
"zu"
|
|
722
|
+
]);
|
|
569
723
|
function languageFromUA(ua) {
|
|
570
724
|
const kwMatch = /\bLanguage\/([a-zA-Z]{2,3}(?:[-_][a-zA-Z]{2,4}){1,2})\b/i.exec(ua);
|
|
571
725
|
if (kwMatch) return normalizeBCP47(kwMatch[1]);
|
|
@@ -575,20 +729,25 @@ function languageFromUA(ua) {
|
|
|
575
729
|
const parts = m[1].replace(/_/g, "-").split("-");
|
|
576
730
|
if (parts.length >= 2) return normalizeBCP47(m[1]);
|
|
577
731
|
}
|
|
732
|
+
const bare = /[;(]\s*([a-z]{2,3})\s*[;)]/g;
|
|
733
|
+
while ((m = bare.exec(ua)) !== null) {
|
|
734
|
+
if (ISO_639_1.has(m[1])) return m[1];
|
|
735
|
+
}
|
|
578
736
|
return "unknown";
|
|
579
737
|
}
|
|
580
738
|
function parseUA(ua, options = {}) {
|
|
581
739
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
|
|
582
740
|
const effectiveNav = (_a = options.ctx) != null ? _a : options.nav;
|
|
583
741
|
const effectiveWindowsVersion = (_c = (_b = options.ctx) == null ? void 0 : _b.windowsVersion) != null ? _c : options.windowsVersion;
|
|
584
|
-
const { browser: rawBrowser, version: rawVersion } = detectBrowser(ua);
|
|
585
|
-
const { os: rawOs, osVersion: rawOsVersion } = detectOs(ua, effectiveWindowsVersion);
|
|
742
|
+
const { browser: rawBrowser, version: rawVersion, browserType } = detectBrowser(ua);
|
|
743
|
+
const { os: rawOs, osVersion: rawOsVersion, osVersionName } = detectOs(ua, effectiveWindowsVersion);
|
|
586
744
|
let os = rawOs;
|
|
587
745
|
let osVersion = rawOsVersion;
|
|
588
746
|
const device = detectDevice(ua, effectiveNav);
|
|
747
|
+
const { vendor, model } = detectVendorModel(ua);
|
|
589
748
|
const arch = detectArch(ua, (_d = options.ctx) != null ? _d : effectiveNav);
|
|
590
749
|
const nav = effectiveNav;
|
|
591
|
-
const { isBot, botName } = detectBot(ua, options.customBotDefs);
|
|
750
|
+
const { isBot, botName, botCategory } = detectBot(ua, options.customBotDefs);
|
|
592
751
|
const isHeadless = detectHeadless(ua);
|
|
593
752
|
const language = options.language || ((nav == null ? void 0 : nav.language) || (nav == null ? void 0 : nav.browserLanguage) ? getLanguage(nav) : "") || languageFromUA(ua);
|
|
594
753
|
const platform = (nav == null ? void 0 : nav.platform) || platformFromUA(ua);
|
|
@@ -630,20 +789,8 @@ function parseUA(ua, options = {}) {
|
|
|
630
789
|
const opVer = (_h = (_g = /OPR\/([\d.]+)/.exec(ua)) != null ? _g : /OPT\/([\d.]+)/.exec(ua)) != null ? _h : /Opera\/([\d.]+)/.exec(ua);
|
|
631
790
|
version = (_i = opVer == null ? void 0 : opVer[1]) != null ? _i : "unknown";
|
|
632
791
|
}
|
|
633
|
-
if (browser === "
|
|
634
|
-
|
|
635
|
-
if (m) {
|
|
636
|
-
browser = m[1];
|
|
637
|
-
version = m[2];
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
if (browser === "Firefox" && nav) {
|
|
641
|
-
try {
|
|
642
|
-
if (typeof clientInformation !== "undefined" || typeof u2f === "undefined") {
|
|
643
|
-
browser = "Firefox Nightly";
|
|
644
|
-
}
|
|
645
|
-
} catch (e) {
|
|
646
|
-
}
|
|
792
|
+
if (browser === "Firefox" && /Firefox\/[\d.]+a\d/.test(ua)) {
|
|
793
|
+
browser = "Firefox Nightly";
|
|
647
794
|
}
|
|
648
795
|
if (os === "iOS" && browser === "Safari") {
|
|
649
796
|
const m = /Version\/([\d.]+)/.exec(ua);
|
|
@@ -685,22 +832,40 @@ function parseUA(ua, options = {}) {
|
|
|
685
832
|
}
|
|
686
833
|
}
|
|
687
834
|
}
|
|
688
|
-
const engine = detectEngine(ua, browser, version);
|
|
689
|
-
const
|
|
835
|
+
const { engine, engineVersion } = detectEngine(ua, browser, version);
|
|
836
|
+
const major = parseInt((_l = version.split(".")[0]) != null ? _l : "", 10);
|
|
837
|
+
const versionMajor = Number.isNaN(major) ? 0 : major;
|
|
690
838
|
const connectionType = (_p = (_o = (_n = (_m = options.ctx) != null ? _m : options.nav) == null ? void 0 : _n.connection) == null ? void 0 : _o.effectiveType) != null ? _p : "unknown";
|
|
839
|
+
const finalOsVersionName = os === "MacOS" || os === "Windows" ? (() => {
|
|
840
|
+
var _a2;
|
|
841
|
+
const map = (_a2 = OS_DEFS.find((d) => d.name === os)) == null ? void 0 : _a2.versionNames;
|
|
842
|
+
if (!map) return "unknown";
|
|
843
|
+
const parts = osVersion.split(".");
|
|
844
|
+
for (let len = parts.length; len >= 1; len--) {
|
|
845
|
+
const key = parts.slice(0, len).join(".");
|
|
846
|
+
if (Object.prototype.hasOwnProperty.call(map, key)) return map[key];
|
|
847
|
+
}
|
|
848
|
+
return "unknown";
|
|
849
|
+
})() : osVersionName;
|
|
691
850
|
return {
|
|
692
851
|
browser,
|
|
693
852
|
version,
|
|
694
853
|
versionMajor,
|
|
854
|
+
browserType: browser === "Brave" ? "browser" : browserType,
|
|
695
855
|
engine,
|
|
856
|
+
engineVersion,
|
|
696
857
|
os,
|
|
697
858
|
osVersion,
|
|
859
|
+
osVersionName: finalOsVersionName,
|
|
698
860
|
device,
|
|
861
|
+
vendor,
|
|
862
|
+
model,
|
|
699
863
|
arch,
|
|
700
864
|
isWebview: isWebview(ua),
|
|
701
865
|
isHeadless,
|
|
702
866
|
isBot,
|
|
703
867
|
botName,
|
|
868
|
+
botCategory,
|
|
704
869
|
language,
|
|
705
870
|
platform,
|
|
706
871
|
connectionType
|
|
@@ -910,7 +1075,7 @@ function deriveWindowsVersion2(platformVersion) {
|
|
|
910
1075
|
return isNaN(major) ? null : major >= 13 ? "11" : "10";
|
|
911
1076
|
}
|
|
912
1077
|
function parseHeaders(headers) {
|
|
913
|
-
var _a, _b, _c, _d, _e;
|
|
1078
|
+
var _a, _b, _c, _d, _e, _f;
|
|
914
1079
|
const normalised = {};
|
|
915
1080
|
for (const key of Object.keys(headers)) {
|
|
916
1081
|
normalised[key.toLowerCase()] = headers[key];
|
|
@@ -927,12 +1092,24 @@ function parseHeaders(headers) {
|
|
|
927
1092
|
const model = unquote(get("sec-ch-ua-model"));
|
|
928
1093
|
const platformVersion = unquote(get("sec-ch-ua-platform-version"));
|
|
929
1094
|
const platform = (_e = unquote(get("sec-ch-ua-platform"))) != null ? _e : "";
|
|
1095
|
+
const fullVersionListRaw = get("sec-ch-ua-full-version-list");
|
|
1096
|
+
const fullVersionList = [];
|
|
1097
|
+
if (fullVersionListRaw) {
|
|
1098
|
+
const re = /"([^"]+)";v="([^"]+)"/g;
|
|
1099
|
+
let m;
|
|
1100
|
+
while ((m = re.exec(fullVersionListRaw)) !== null) {
|
|
1101
|
+
fullVersionList.push({ brand: m[1], version: m[2] });
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
930
1104
|
const highEntropyData = {};
|
|
931
1105
|
if (architecture !== void 0) highEntropyData.architecture = architecture;
|
|
932
1106
|
if (bitness !== void 0) highEntropyData.bitness = bitness;
|
|
933
1107
|
if (model !== void 0) highEntropyData.model = model;
|
|
934
1108
|
if (platformVersion !== void 0) highEntropyData.platformVersion = platformVersion;
|
|
1109
|
+
if (fullVersionList.length > 0) highEntropyData.fullVersionList = fullVersionList;
|
|
935
1110
|
const isMobile = get("sec-ch-ua-mobile") === "?1";
|
|
1111
|
+
const secCHUA = (_f = get("sec-ch-ua")) != null ? _f : "";
|
|
1112
|
+
const hasBrave = /"Brave"/.test(secCHUA);
|
|
936
1113
|
const windowsVersion = platform === "Windows" ? deriveWindowsVersion2(platformVersion) : null;
|
|
937
1114
|
const ctx = {
|
|
938
1115
|
userAgent: ua,
|
|
@@ -940,7 +1117,8 @@ function parseHeaders(headers) {
|
|
|
940
1117
|
language,
|
|
941
1118
|
maxTouchPoints: isMobile ? 1 : 0,
|
|
942
1119
|
highEntropyData: Object.keys(highEntropyData).length > 0 ? highEntropyData : void 0,
|
|
943
|
-
windowsVersion
|
|
1120
|
+
windowsVersion,
|
|
1121
|
+
hasBrave
|
|
944
1122
|
};
|
|
945
1123
|
return parseUA(ua, { ctx });
|
|
946
1124
|
}
|
|
@@ -970,6 +1148,7 @@ exports.detectDevice = detectDevice;
|
|
|
970
1148
|
exports.detectEngine = detectEngine;
|
|
971
1149
|
exports.detectHeadless = detectHeadless;
|
|
972
1150
|
exports.detectOS = detectOs;
|
|
1151
|
+
exports.detectVendorModel = detectVendorModel;
|
|
973
1152
|
exports.getEnvContext = getEnvContext;
|
|
974
1153
|
exports.getLanguage = getLanguage;
|
|
975
1154
|
exports.getNavContext = getNavContext;
|