mirror of
https://github.com/faisalman/ua-parser-js.git
synced 2025-11-15 22:52:16 +03:00
Compare commits
52 Commits
2.0.4-pro-
...
2.0.6-pro-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b061251e82 | ||
|
|
061cf0e90f | ||
|
|
2882014f0e | ||
|
|
3eea0643c5 | ||
|
|
5f1ed83225 | ||
|
|
5349bb52ed | ||
|
|
9ba4d2b207 | ||
|
|
4c935c0139 | ||
|
|
ae7b5e15e5 | ||
|
|
44165a6e01 | ||
|
|
fc5125042c | ||
|
|
4e6259ad7f | ||
|
|
b3bc89c463 | ||
|
|
5749302c47 | ||
|
|
6565d24567 | ||
|
|
b3281b7c12 | ||
|
|
bd6bb216bd | ||
|
|
e7e7aaad4c | ||
|
|
95d2b151a3 | ||
|
|
737cdd4d40 | ||
|
|
74064b0cac | ||
|
|
5b5e33681f | ||
|
|
3ea5721e86 | ||
|
|
a4342b01d4 | ||
|
|
31bf36c36d | ||
|
|
9bef871e41 | ||
|
|
b1d9dcafcd | ||
|
|
146f182533 | ||
|
|
ce242a362f | ||
|
|
2078b1ec92 | ||
|
|
7dcbb8def3 | ||
|
|
f810a6d1d9 | ||
|
|
0e05332609 | ||
|
|
48a1f34c28 | ||
|
|
fb1ed5cf6b | ||
|
|
3e65196b57 | ||
|
|
4e421e72fe | ||
|
|
98cf19c8c5 | ||
|
|
c9badeb345 | ||
|
|
9003fe5724 | ||
|
|
975c4860f4 | ||
|
|
647b6232bd | ||
|
|
95485f7b5d | ||
|
|
74ef71cf63 | ||
|
|
9e6dff6dc3 | ||
|
|
bf5155ec8a | ||
|
|
ecbc0336b6 | ||
|
|
ab299a23b7 | ||
|
|
3fe137e533 | ||
|
|
0bb6e24837 | ||
|
|
a19977ce4c | ||
|
|
088383b9bd |
61
CHANGELOG.md
61
CHANGELOG.md
@@ -23,8 +23,12 @@
|
||||
- **Support for Custom/Predefined Extensions:**
|
||||
- Pass custom regexes or predefined extensions as a list to `UAParser()`
|
||||
|
||||
- **Support for CLI Parsing:**
|
||||
- Parse a user-agent directly from the command line using `npx ua-parser-js "[User-Agent]"`
|
||||
- **Support for CLI Processing:**
|
||||
- Directly parse user-agent strings from the command line:
|
||||
`npx ua-parser-js "<User-Agent>"`
|
||||
- Process batch data from files:
|
||||
`npx ua-parser-js --input-file=log.txt >> result.json` or
|
||||
`npx ua-parser-js --input-file=log.txt --output-file=result.json`
|
||||
|
||||
- **Enhanced Detection with Client Hints:**
|
||||
- `withClientHints()`: Improves detection accuracy by leveraging client hints
|
||||
@@ -65,6 +69,49 @@
|
||||
|
||||
---
|
||||
|
||||
## Version 2.0.6
|
||||
- Add new CLI feature: processing batch user-agent data from file and output as JSON
|
||||
- Fix `setUA()`: trim leading space from user-agent string input
|
||||
- Replace `undici` dependency with node's internal `Headers`
|
||||
- Add new browser: Bing, Qwant
|
||||
- Add new device vendor: Hisense, Wiko
|
||||
- Improve browser detection: Mozilla, Pale Moon
|
||||
- Improve CPU detection: 68k
|
||||
- Improve device detection: Apple, BlackBerry, Huawei, Nokia, Xiaomi
|
||||
- Improve OS detection: iOS 26
|
||||
- `extensions` submodule:
|
||||
- Add new fetcher: Discordbot, KeybaseBot, Slackbot, Slackbot-LinkExpanding, Slack-ImgProxy, Twitterbot
|
||||
- Add new crawler: Qwantbot-news, SurdotlyBot, SwiftBot
|
||||
|
||||
## Version 2.0.5
|
||||
|
||||
- Add new browser: Zalo
|
||||
- Add new CPU arch: alpha
|
||||
- Add new device vendor: Philips
|
||||
- Improve device detection: Pico
|
||||
- Fix parsing error on pages with modified Array prototypes
|
||||
- Improve type declarations:
|
||||
- Replace `node-fetch` dependency with `undici`
|
||||
- Replace hardcoded string values with enum from `enum` submodule
|
||||
- `enums` submodule:
|
||||
- Add `Extension` enum for `extensions` submodule
|
||||
- Type declaration file now automatically generated using build script
|
||||
- Naming adjustments:
|
||||
- `Browser` => `BrowserName`
|
||||
- `CPU` => `CPUArch`
|
||||
- `Device` => `DeviceType`
|
||||
- `Vendor` => `DeviceVendor`
|
||||
- `Engine` => `EngineName`
|
||||
- `OS` => `OSName`
|
||||
- `extensions` submodule:
|
||||
- Add new crawlers:
|
||||
APIs-Google, Algolia Crawler, Algolia Crawler Renderscript, Baidu-ADS, BLEXBot, botify, Bravebot, Claude-Web, cohere-training-data-crawler, contxbot, Cotoyogi, Coveobot, CriteoBot, DeepSeekBot, DuckDuckGo-Favicons-Bot, Elastic, FirecrawlAgent, Freespoke, Google-CloudVertexBot, HuggingFace-Bot, Kagibot, Kangaroo Bot, marginalia, msnbot, OnCrawl, Replicate-Bot, RunPod-Bot, SBIntuitionsBot, SeekportBot, Siteimprove, Sogou Pic Spider, TikTokSpider, TwinAgent, v0bot, webzio, Webzio-Extended, xAI-Bot, YandexAccessibilityBot, YandexAdditionalBot, YandexAdNet, YandexBot MirrorDetector, YandexBlogs, YandexComBot, YandexFavicons, YandexImageResizer, YandexImages, YandexMarket, YandexMetrika, YandexMedia, YandexMobileBot, YandexMobileScreenShotBot, YandexNews, YandexOntoDB, YandexOntoDBAPI, YandexPartner, YandexRCA, YandexRenderResourcesBot, YandexScreenshotBot, YandexSpravBot, YandexTracker, YandexVertis, YandexVerticals, YandexVideo, YandexVideoParser, YandexWebmaster, YepBot, ZumBot
|
||||
- Add new fetchers:
|
||||
Asana, bitlybot, Blueno, BufferLinkPreviewBot, Chrome-Lighthouse, Gemini-Deep-Research, HubSpot Page Fetcher, kakaotalk-scrap, vercel-favicon-bot, vercel-screenshot-bot, vercelflags, verceltracing, YaDirectFetcher, YandexCalendar, YandexDirect, YandexDirectDyn, YandexForDomain, YandexPagechecker, YandexSearchShop, YandexSitelinks, YandexUserproxy
|
||||
- `helpers` submodule:
|
||||
- Add some crawler to `isAIBot()`:
|
||||
Bravebot, cohere-training-data-crawler, FirecrawlAgent, HuggingFace-Bot, Kangaroo Bot, PanguBot, Replicate-Bot, RunPod-Bot, TikTokSpider, Together-Bot, v0bot, xAI-Bot
|
||||
|
||||
## Version 2.0.4
|
||||
|
||||
- Add new browser: Edge WebView, Edge WebView2
|
||||
@@ -240,6 +287,16 @@
|
||||
|
||||
---
|
||||
|
||||
## Version 0.7.41 / 1.0.41
|
||||
- Add new browser: Daum, Ladybird
|
||||
- Add new device vendor: HMD
|
||||
- Add new engine: LibWeb
|
||||
- Add new os: Windows IoT, Ubuntu Touch
|
||||
- Improve cpu detection: ARM, x86
|
||||
- Improve device vendor detection: Apple, Archos, Generic, Google, Honor, Huawei, Infinix, Nvidia, Lenovo, Nokia, OnePlus, Xiaomi
|
||||
- Improve device type detection: smarttv, wearables
|
||||
- Improve os detection: Linux, Symbian
|
||||
|
||||
## Version 0.7.40 / 1.0.40
|
||||
- Add new browser: 115, LibreWolf, Slimboat, Slimjet
|
||||
- Add new device: Advan, Cat, Energizer, IMO, Micromax, Smartfren
|
||||
|
||||
@@ -22,8 +22,12 @@ https://docs.uaparser.dev
|
||||
import { UAParser } from '@ua-parser-js/pro-personal';
|
||||
```
|
||||
|
||||
```js
|
||||
import { isFrozenUA } from '@ua-parser-js/pro-personal/helpers';
|
||||
```
|
||||
|
||||
# License
|
||||
|
||||
UAParser.js PRO Personal
|
||||
|
||||
Copyright (c) 2023-2024 Faisal Salman <<f@faisalman.com>>
|
||||
Copyright (c) 2023-2025 Faisal Salman <<f@faisalman.com>>
|
||||
|
||||
4
dist/ua-parser.min.js
vendored
4
dist/ua-parser.min.js
vendored
File diff suppressed because one or more lines are too long
4
dist/ua-parser.min.mjs
vendored
4
dist/ua-parser.min.mjs
vendored
File diff suppressed because one or more lines are too long
4
dist/ua-parser.pack.js
vendored
4
dist/ua-parser.pack.js
vendored
File diff suppressed because one or more lines are too long
4
dist/ua-parser.pack.mjs
vendored
4
dist/ua-parser.pack.mjs
vendored
File diff suppressed because one or more lines are too long
122
package-lock.json
generated
122
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@ua-parser-js/pro-personal",
|
||||
"version": "2.0.4",
|
||||
"version": "2.0.6",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ua-parser-js/pro-personal",
|
||||
"version": "2.0.4",
|
||||
"version": "2.0.6",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@@ -23,10 +23,8 @@
|
||||
],
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"dependencies": {
|
||||
"@types/node-fetch": "^2.6.12",
|
||||
"detect-europe-js": "^0.1.2",
|
||||
"is-standalone-pwa": "^0.1.1",
|
||||
"node-fetch": "^2.7.0",
|
||||
"ua-is-frozen": "^0.1.2"
|
||||
},
|
||||
"bin": {
|
||||
@@ -402,23 +400,6 @@
|
||||
"integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.13.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz",
|
||||
"integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.20.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node-fetch": {
|
||||
"version": "2.6.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.12.tgz",
|
||||
"integrity": "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==",
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"form-data": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/normalize-package-data": {
|
||||
"version": "2.4.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz",
|
||||
@@ -519,11 +500,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
@@ -664,17 +640,6 @@
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
@@ -753,14 +718,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-europe-js": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/detect-europe-js/-/detect-europe-js-0.1.2.tgz",
|
||||
@@ -1011,19 +968,6 @@
|
||||
"flat": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz",
|
||||
"integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
@@ -1591,25 +1535,6 @@
|
||||
"node": ">=8.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/min-indent": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
|
||||
@@ -1963,25 +1888,6 @@
|
||||
"node": "^10 || ^12 || >=13.7"
|
||||
}
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
||||
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
|
||||
"dependencies": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "4.x || >=6.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"encoding": "^0.1.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"encoding": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/normalize-package-data": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz",
|
||||
@@ -2713,11 +2619,6 @@
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tr46": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
|
||||
},
|
||||
"node_modules/trim-newlines": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz",
|
||||
@@ -2791,11 +2692,6 @@
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.20.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
|
||||
"integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="
|
||||
},
|
||||
"node_modules/validate-npm-package-license": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
|
||||
@@ -2806,20 +2702,6 @@
|
||||
"spdx-expression-parse": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
|
||||
},
|
||||
"node_modules/whatwg-url": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
|
||||
"dependencies": {
|
||||
"tr46": "~0.0.3",
|
||||
"webidl-conversions": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
|
||||
16
package.json
16
package.json
@@ -1,25 +1,25 @@
|
||||
{
|
||||
"title": "UAParser.js PRO Personal",
|
||||
"name": "@ua-parser-js/pro-personal",
|
||||
"version": "2.0.4",
|
||||
"version": "2.0.6",
|
||||
"author": "Faisal Salman <f@faisalman.com> (http://faisalman.com)",
|
||||
"description": "Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent & Client Hints data. Supports browser & node.js environment",
|
||||
"keywords": [
|
||||
"user-agent",
|
||||
"client-hints",
|
||||
"parser",
|
||||
"browser",
|
||||
"engine",
|
||||
"os",
|
||||
"device",
|
||||
"cpu",
|
||||
"jquery-plugin",
|
||||
"ecosystem:jquery",
|
||||
"ua-parser-js",
|
||||
"browser-detection",
|
||||
"device-detection",
|
||||
"os-detection",
|
||||
"bot-detection"
|
||||
"bot-detection",
|
||||
"ai-detection",
|
||||
"app-detection",
|
||||
"crawler-detection"
|
||||
],
|
||||
"homepage": "https://uaparser.dev",
|
||||
"contributors": [
|
||||
@@ -220,15 +220,13 @@
|
||||
"test:eslint": "eslint src && eslint script",
|
||||
"test:jshint": "jshint src/main",
|
||||
"test:lockfile-lint": "npx lockfile-lint -p package-lock.json",
|
||||
"test:mocha": "mocha test/unit",
|
||||
"test:mocha": "mocha --recursive test/unit",
|
||||
"test:playwright": "npx playwright install && playwright test test/e2e --browser all"
|
||||
},
|
||||
"dependencies": {
|
||||
"detect-europe-js": "^0.1.2",
|
||||
"is-standalone-pwa": "^0.1.1",
|
||||
"ua-is-frozen": "^0.1.2",
|
||||
"node-fetch": "^2.7.0",
|
||||
"@types/node-fetch": "^2.6.12"
|
||||
"ua-is-frozen": "^0.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/parser": "7.15.8",
|
||||
|
||||
@@ -2,15 +2,18 @@
|
||||
/* jshint esversion: 6 */
|
||||
const fs = require('fs');
|
||||
|
||||
const generateMJS = (module) => {
|
||||
let { src, dest, title, replacements } = module;
|
||||
let text = fs.readFileSync(src, 'utf-8');
|
||||
|
||||
replacements.push(
|
||||
const defaultReplacements = {
|
||||
mjs: [
|
||||
[/const (.+?)\s*=\s*require\(\'\.(.+)\'\)/ig, 'import $1 from \'\.$2.mjs\''],
|
||||
[/const (.+?)\s*=\s*require\(\'(.+)\'\)/ig, 'import $1 from \'$2\''],
|
||||
[/module\.exports =/ig, 'export']
|
||||
);
|
||||
]
|
||||
}
|
||||
|
||||
const generateFile = (module) => {
|
||||
let { src, dest, title, replacements } = module;
|
||||
let text = fs.readFileSync(src, 'utf-8');
|
||||
|
||||
replacements.forEach(rep => {
|
||||
text = text.replace(rep[0], rep[1]);
|
||||
});
|
||||
@@ -18,42 +21,54 @@ const generateMJS = (module) => {
|
||||
console.log(`Generate ${dest}`);
|
||||
|
||||
fs.writeFileSync(dest,
|
||||
`// Generated ESM version of ${title}
|
||||
`// ${title}
|
||||
// DO NOT EDIT THIS FILE!
|
||||
// Source: /${src}
|
||||
|
||||
${text}`, 'utf-8');
|
||||
|
||||
};
|
||||
|
||||
const modules = [
|
||||
const files = [
|
||||
{
|
||||
src : 'src/main/ua-parser.js',
|
||||
dest : 'src/main/ua-parser.mjs',
|
||||
title : 'ua-parser-js',
|
||||
title : 'Generated ESM version of ua-parser-js',
|
||||
replacements : [
|
||||
[/\(func[\s\S]+strict\';/ig, ''],
|
||||
[/esversion\: 3/ig, 'esversion: 6'],
|
||||
[/\/[\/\s]+export[\s\S]+/ig,'export {UAParser};']
|
||||
[/\/[\/\s]+export[\s\S]+/ig,'export {UAParser};'],
|
||||
...defaultReplacements.mjs
|
||||
]
|
||||
},{
|
||||
},
|
||||
{
|
||||
src : 'src/enums/ua-parser-enums.js',
|
||||
dest :'src/enums/ua-parser-enums.mjs',
|
||||
title : 'ua-parser-js/enums',
|
||||
replacements : []
|
||||
title : 'Generated ESM version of ua-parser-js/enums',
|
||||
replacements : [...defaultReplacements.mjs]
|
||||
},
|
||||
{
|
||||
src : 'src/enums/ua-parser-enums.js',
|
||||
dest :'src/enums/ua-parser-enums.d.ts',
|
||||
title : 'Generated type declarations of ua-parser-js/enums',
|
||||
replacements : [
|
||||
[/(const .+) = object\.freeze\(/ig, 'export $1: Readonly<'],
|
||||
[/(const .+) =( .+;)/ig, 'export $1: typeof$2'],
|
||||
[/}\);/ig, '}>;'],
|
||||
[/module\.exports =.+/igs, '']
|
||||
]
|
||||
},
|
||||
{
|
||||
src : 'src/extensions/ua-parser-extensions.js',
|
||||
dest : 'src/extensions/ua-parser-extensions.mjs',
|
||||
title : 'ua-parser-js/extensions',
|
||||
replacements : []
|
||||
title : 'Generated ESM version of ua-parser-js/extensions',
|
||||
replacements : [...defaultReplacements.mjs]
|
||||
},
|
||||
{
|
||||
src : 'src/helpers/ua-parser-helpers.js',
|
||||
dest : 'src/helpers/ua-parser-helpers.mjs',
|
||||
title : 'ua-parser-js/helpers',
|
||||
replacements : []
|
||||
title : 'Generated ESM version of ua-parser-js/helpers',
|
||||
replacements : [...defaultReplacements.mjs]
|
||||
}
|
||||
];
|
||||
|
||||
modules.forEach(module => generateMJS(module));
|
||||
files.forEach(module => generateFile(module));
|
||||
@@ -1,4 +1,94 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const UAParser = require('ua-parser-js');
|
||||
console.log(JSON.stringify(process.argv.slice(2).map(ua => UAParser(ua)), null, 4));
|
||||
try {
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const { performance } = require('node:perf_hooks');
|
||||
const readline = require('node:readline');
|
||||
const { parseArgs } = require('node:util');
|
||||
const UAParser = require('../src/main/ua-parser');
|
||||
const { Bots, Emails, ExtraDevices, InApps, Vehicles } = require('../src/extensions/ua-parser-extensions');
|
||||
|
||||
if (!process.argv[2].startsWith('-')) {
|
||||
|
||||
const results = process.argv.slice(2).map(ua => UAParser(ua));
|
||||
console.log(JSON.stringify(results, null, 4));
|
||||
process.exit(0);
|
||||
|
||||
} else if (['-h', '--help'].includes(process.argv[2])) {
|
||||
|
||||
console.log('Usage: npx ua-parser-js <string>');
|
||||
console.log(' or npx ua-parser-js --input-file <filepath> [--output-file <filepath>]');
|
||||
console.log('-i, --input-file');
|
||||
console.log('-o, --output-file');
|
||||
process.exit(0);
|
||||
|
||||
} else {
|
||||
|
||||
const startPerf = performance.now();
|
||||
const {
|
||||
values: {
|
||||
'input-file': inputFile,
|
||||
'output-file': outputFile
|
||||
},
|
||||
} = parseArgs({
|
||||
options: {
|
||||
'input-file': { type: 'string', short: 'i' },
|
||||
'output-file': { type: 'string', short: 'o' }
|
||||
}
|
||||
});
|
||||
|
||||
if (!inputFile) {
|
||||
console.error('Input file must be present');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const inputPath = path.resolve(__dirname, inputFile);
|
||||
const outputPath = outputFile ? path.resolve(__dirname, outputFile) : null;
|
||||
|
||||
if (!fs.existsSync(inputPath)) {
|
||||
console.error(`Input file not found: ${inputPath}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const inputStream = fs.createReadStream(inputPath, 'utf8');
|
||||
const rl = readline.createInterface({
|
||||
input: inputStream,
|
||||
crlfDelay: Infinity
|
||||
});
|
||||
|
||||
const outputStream = outputPath ? fs.createWriteStream(outputPath, { encoding : 'utf8' }) : process.stdout;
|
||||
|
||||
const uap = new UAParser([Bots, Emails, ExtraDevices, InApps, Vehicles]);
|
||||
let lineNumber = 0;
|
||||
|
||||
outputStream.write('[\n');
|
||||
|
||||
rl.on('line', line => {
|
||||
const result = uap.setUA(line).getResult();
|
||||
const json = JSON.stringify(result, null, 4);
|
||||
if (lineNumber > 0) outputStream.write(',\n');
|
||||
outputStream.write(json);
|
||||
lineNumber++;
|
||||
});
|
||||
|
||||
rl.on('close', () => {
|
||||
outputStream.write('\n]');
|
||||
if (outputPath) {
|
||||
outputStream.end(() => {
|
||||
const finishPerf = performance.now();
|
||||
console.log(`Done!`);
|
||||
console.log(`Number of lines found: ${lineNumber}`);
|
||||
console.log(`Task finished in: ${(finishPerf - startPerf).toFixed(3)}ms`);
|
||||
console.log(`Output written to: ${outputPath}`);
|
||||
process.exit(0);
|
||||
});
|
||||
} else {
|
||||
process.exit(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
}
|
||||
1108
src/enums/ua-parser-enums.d.ts
vendored
1108
src/enums/ua-parser-enums.d.ts
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////
|
||||
/* Enums for UAParser.js v2.0.4
|
||||
/* Enums for UAParser.js v2.0.6
|
||||
https://github.com/faisalman/ua-parser-js
|
||||
Author: Faisal Salman <f@faisalman.com>
|
||||
UAParser.js PRO Personal License */
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
/*jshint esversion: 6 */
|
||||
|
||||
const Browser = Object.freeze({
|
||||
const BrowserName = Object.freeze({
|
||||
'115': '115',
|
||||
'2345': '2345',
|
||||
'360': '360',
|
||||
@@ -20,6 +20,7 @@ const Browser = Object.freeze({
|
||||
AVG: 'AVG Secure Browser',
|
||||
BAIDU: 'Baidu Browser',
|
||||
BASILISK: 'Basilisk',
|
||||
BING: 'Bing',
|
||||
BLAZER: 'Blazer',
|
||||
BOLT: 'Bolt',
|
||||
BOWSER: 'Bowser',
|
||||
@@ -125,6 +126,7 @@ const Browser = Object.freeze({
|
||||
QUARK: 'Quark',
|
||||
QUPZILLA: 'QupZilla',
|
||||
QUTEBROWSER: 'qutebrowser',
|
||||
QWANT: 'Qwant',
|
||||
REKONQ: 'rekonq',
|
||||
ROCKMELT: 'Rockmelt',
|
||||
SAFARI: 'Safari',
|
||||
@@ -158,10 +160,15 @@ const Browser = Object.freeze({
|
||||
WEIBO: 'Weibo',
|
||||
WHALE: 'Whale',
|
||||
WOLVIC: 'Wolvic',
|
||||
YANDEX: 'Yandex'
|
||||
YANDEX: 'Yandex',
|
||||
ZALO: 'Zalo'
|
||||
|
||||
// TODO : test!
|
||||
});
|
||||
/**
|
||||
* @deprecated Use `BrowserName` instead
|
||||
*/
|
||||
const Browser = BrowserName;
|
||||
|
||||
const BrowserType = Object.freeze({
|
||||
CRAWLER: 'crawler',
|
||||
@@ -173,8 +180,9 @@ const BrowserType = Object.freeze({
|
||||
LIBRARY: 'library'
|
||||
});
|
||||
|
||||
const CPU = Object.freeze({
|
||||
const CPUArch = Object.freeze({
|
||||
'68K': '68k',
|
||||
ALPHA: 'alpha',
|
||||
ARM : 'arm',
|
||||
ARM_64: 'arm64',
|
||||
ARM_HF: 'armhf',
|
||||
@@ -192,8 +200,12 @@ const CPU = Object.freeze({
|
||||
X86: 'ia32',
|
||||
X86_64: 'amd64'
|
||||
});
|
||||
/**
|
||||
* @deprecated Use `CPUArch` instead
|
||||
*/
|
||||
const CPU = CPUArch;
|
||||
|
||||
const Device = Object.freeze({
|
||||
const DeviceType = Object.freeze({
|
||||
CONSOLE: 'console',
|
||||
DESKTOP: 'desktop',
|
||||
EMBEDDED: 'embedded',
|
||||
@@ -203,8 +215,12 @@ const Device = Object.freeze({
|
||||
WEARABLE: 'wearable',
|
||||
XR: 'xr'
|
||||
});
|
||||
/**
|
||||
* @deprecated Use `DeviceType` instead
|
||||
*/
|
||||
const Device = DeviceType;
|
||||
|
||||
const Vendor = Object.freeze({
|
||||
const DeviceVendor = Object.freeze({
|
||||
ACER: 'Acer',
|
||||
ADVAN: 'Advan',
|
||||
ALCATEL: 'Alcatel',
|
||||
@@ -225,6 +241,7 @@ const Vendor = Object.freeze({
|
||||
GEEKSPHONE: 'GeeksPhone',
|
||||
GENERIC: 'Generic',
|
||||
GOOGLE: 'Google',
|
||||
HISENSE: 'Hisense',
|
||||
HMD: 'HMD',
|
||||
HP: 'HP',
|
||||
HTC: 'HTC',
|
||||
@@ -252,6 +269,7 @@ const Vendor = Object.freeze({
|
||||
PALM: 'Palm',
|
||||
PANASONIC: 'Panasonic',
|
||||
PEBBLE: 'Pebble',
|
||||
PHILIPS: 'Philips',
|
||||
PICO: 'Pico',
|
||||
POLYTRON: 'Polytron',
|
||||
REALME: 'Realme',
|
||||
@@ -266,12 +284,13 @@ const Vendor = Object.freeze({
|
||||
SPRINT: 'Sprint',
|
||||
TCL: 'TCL',
|
||||
TECHNISAT: 'TechniSAT',
|
||||
TECNO: 'Tecno',
|
||||
TECNO: 'TECNO',
|
||||
TESLA: 'Tesla',
|
||||
ULEFONE: 'Ulefone',
|
||||
VIVO: 'Vivo',
|
||||
VIZIO: 'Vizio',
|
||||
VODAFONE: 'Vodafone',
|
||||
WIKO: 'Wiko',
|
||||
XBOX: 'Xbox',
|
||||
XIAOMI: 'Xiaomi',
|
||||
ZEBRA: 'Zebra',
|
||||
@@ -279,8 +298,12 @@ const Vendor = Object.freeze({
|
||||
|
||||
// TODO : test!
|
||||
});
|
||||
/**
|
||||
* @deprecated Use `DeviceVendor` instead
|
||||
*/
|
||||
const Vendor = DeviceVendor;
|
||||
|
||||
const Engine = Object.freeze({
|
||||
const EngineName = Object.freeze({
|
||||
AMAYA: 'Amaya',
|
||||
ARKWEB: 'ArkWeb',
|
||||
BLINK: 'Blink',
|
||||
@@ -302,8 +325,12 @@ const Engine = Object.freeze({
|
||||
W3M: 'w3m',
|
||||
WEBKIT: 'WebKit'
|
||||
});
|
||||
/**
|
||||
* @deprecated Use `EngineName` instead
|
||||
*/
|
||||
const Engine = EngineName;
|
||||
|
||||
const OS = Object.freeze({
|
||||
const OSName = Object.freeze({
|
||||
AIX: 'AIX',
|
||||
AMIGA_OS: 'Amiga OS',
|
||||
ANDROID: 'Android',
|
||||
@@ -399,13 +426,331 @@ const OS = Object.freeze({
|
||||
|
||||
// TODO : test!
|
||||
});
|
||||
/**
|
||||
* @deprecated Use `OSName` instead
|
||||
*/
|
||||
const OS = OSName;
|
||||
|
||||
/*////////////////////////////////
|
||||
* Enums for Extensions submodule
|
||||
*///////////////////////////////
|
||||
|
||||
const Extension = Object.freeze({
|
||||
BrowserName: {
|
||||
CLI: {
|
||||
CURL: 'curl',
|
||||
ELINKS: 'ELinks',
|
||||
HTTPIE: 'HTTPie',
|
||||
LYNX: 'Lynx',
|
||||
WGET: 'Wget'
|
||||
},
|
||||
Crawler: {
|
||||
AHREFS_BOT: 'AhrefsBot',
|
||||
AI2_BOT: 'AI2Bot',
|
||||
AIHIT_BOT: 'aiHitBot',
|
||||
ALGOLIA_CRAWLER: 'Algolia Crawler',
|
||||
APPLE_BOT: 'Applebot',
|
||||
APPLE_BOT_EXTENDED: 'Applebot-Extended',
|
||||
ASK_TEOMA: 'Teoma',
|
||||
AMAZON_BOT: 'Amazonbot',
|
||||
AMAZON_CONTXBOT: 'contxbot',
|
||||
ANTHROPIC_AI: 'anthropic-ai',
|
||||
ANTHROPIC_CLAUDE_BOT: 'ClaudeBot',
|
||||
ANTHROPIC_CLAUDE_SEARCHBOT: 'Claude-SearchBot',
|
||||
ANTHROPIC_CLAUDE_WEB: 'Claude-Web',
|
||||
ARCHIVEORG_BOT: 'archive.org_bot',
|
||||
BAIDU_ADS: 'Baidu-ADS',
|
||||
BAIDU_SPIDER: 'Baiduspider',
|
||||
BAIDU_SPIDER_ADS: 'Baiduspider-ads',
|
||||
BAIDU_SPIDER_CPRO: 'Baiduspider-cpro',
|
||||
BAIDU_SPIDER_FAVO: 'Baiduspider-favo',
|
||||
BAIDU_SPIDER_IMAGE: 'Baiduspider-image',
|
||||
BAIDU_SPIDER_NEWS: 'Baiduspider-news',
|
||||
BAIDU_SPIDER_RENDER: 'Baiduspider-render',
|
||||
BAIDU_SPIDER_VIDEO: 'Baiduspider-video',
|
||||
BLEX_BOT: 'BLEXBot',
|
||||
BOTIFY: 'botify',
|
||||
BRAVE_BOT: 'Bravebot',
|
||||
BYTEDANCE_BYTESPIDER: 'Bytespider',
|
||||
BYTEDANCE_TIKTOKSPIDER: 'TikTokSpider',
|
||||
COMMON_CRAWL_CCBOT: 'CCBot',
|
||||
COCCOC_BOT_WEB: 'coccocbot-web',
|
||||
COCCOC_BOT_IMAGE: 'coccocbot-image',
|
||||
COHERE_TRAINING_DATA_CRAWLER: 'cohere-training-data-crawler',
|
||||
COTOYOGI: 'Cotoyogi',
|
||||
COVEO_BOT: 'Coveobot',
|
||||
CRITEO_BOT: 'CriteoBot',
|
||||
DATAFORSEO_BOT: 'DataForSeoBot',
|
||||
DAUM: 'Daum',
|
||||
DAUM_DAUMOA: 'Daumoa',
|
||||
DAUM_DAUMOA_IMAGE: 'Daumoa-image',
|
||||
DEEPSEEK_BOT: 'DeepSeekBot',
|
||||
DIFFBOT: 'Diffbot',
|
||||
DUCKDUCKGO_BOT: 'DuckDuckBot',
|
||||
DUCKDUCKGO_FAVICONS_BOT: 'DuckDuckGo-Favicons-Bot',
|
||||
ELASTIC: 'Elastic',
|
||||
ELASTIC_SWIFTYPE_BOT: 'Swiftbot',
|
||||
EXALEAD_EXABOT: 'Exabot',
|
||||
FIRECRAWL_AGENT: 'FirecrawlAgent',
|
||||
FREESPOKE: 'Freespoke',
|
||||
GOOGLE_ADSBOT: 'AdsBot-Google',
|
||||
GOOGLE_ADSBOT_MOBILE: 'Adsbot-Google-Mobile',
|
||||
GOOGLE_ADSENSE: 'AdSense',
|
||||
GOOGLE_APIS: 'APIs-Google',
|
||||
GOOGLE_BOT: 'Googlebot',
|
||||
GOOGLE_BOT_IMAGE: 'Googlebot-Image',
|
||||
GOOGLE_BOT_NEWS: 'Googlebot-News',
|
||||
GOOGLE_BOT_VIDEO: 'Googlebot-Video',
|
||||
GOOGLE_CLOUDVERTEXBOT: 'Google-CloudVertexBot',
|
||||
GOOGLE_EXTENDED: 'Google-Extended',
|
||||
GOOGLE_INSPECTIONTOOL: 'Google-InspectionTool',
|
||||
GOOGLE_OTHER: 'GoogleOther',
|
||||
GOOGLE_OTHER_IMAGE: 'GoogleOther-Image',
|
||||
GOOGLE_OTHER_VIDEO: 'GoogleOther-Video',
|
||||
GOOGLE_SAFETY: 'Google-Safety',
|
||||
GOOGLE_STOREBOT: 'Storebot-Google',
|
||||
HIVE_IMAGESIFTBOT: 'ImagesiftBot',
|
||||
HUAWEI_PANGUBOT: 'PanguBot',
|
||||
HUAWEI_PETALBOT: 'PetalBot',
|
||||
HUGGINGFACE_BOT: 'HuggingFace-Bot',
|
||||
HUNTER_VELENPUBLICWEBCRAWLER: 'VelenPublicWebCrawler',
|
||||
IA_ARCHIVER: 'ia_archiver',
|
||||
IASK_BOT: 'iAskBot',
|
||||
KAGI_BOT: 'Kagibot',
|
||||
KANGAROO_BOT: 'Kangaroo Bot',
|
||||
LINE_SPIDER: 'Linespider',
|
||||
LINKEDIN_BOT: 'LinkedInBot',
|
||||
MAGPIE_CRAWLER: 'magpie-crawler',
|
||||
MARGINALIA: 'marginalia',
|
||||
META_EXTERNALAGENT: 'meta-externalagent',
|
||||
META_FACEBOOKBOT: 'FacebookBot',
|
||||
META_FACEBOOKCATALOG: 'facebookcatalog',
|
||||
META_FACEBOOKEXTERNALHIT: 'facebookexternalhit',
|
||||
MAJESTIC_MJ12BOT: 'MJ12bot',
|
||||
MICROSOFT_BINGBOT: 'Bingbot',
|
||||
MICROSOFT_MSNBOT: 'msnbot',
|
||||
MICROSOFT_ADIDXBOT: 'adidxbot',
|
||||
MOJEEK_BOT: 'MojeekBot',
|
||||
MOZ_DOTBOT: 'DotBot',
|
||||
ONCRAWL: 'OnCrawl',
|
||||
ONESPOT_SCRAPERBOT: 'Onespot-ScraperBot',
|
||||
OPENAI_GPTBOT: 'GPTBot',
|
||||
OPENAI_SEARCH_BOT: 'OAI-SearchBot',
|
||||
PERPLEXITY_BOT: 'PerplexityBot',
|
||||
QIHOO_360_SPIDER: '360Spider',
|
||||
QWANT_BOT: 'Qwantbot',
|
||||
QWANT_BOT_NEWS: 'Qwantbot-news',
|
||||
REPLICATE_BOT: 'Replicate-Bot',
|
||||
RUNPOD_BOT: 'RunPod-Bot',
|
||||
SB_INTUITIONS_BOT: 'SBIntuitionsBot',
|
||||
SEEKPORT_BOT: 'SeekportBot',
|
||||
SEMRUSH_BOT: 'SemrushBot',
|
||||
SEMRUSH_BOT_BACKLINK: 'SemrushBot-BA',
|
||||
SEMRUSH_BOT_CONTENTSHAKE: 'SemrushBot-OCOB',
|
||||
SEMRUSH_BOT_SEO_CHECKER: 'SemrushBot-SI',
|
||||
SEZNAM_BOT: 'SeznamBot',
|
||||
SITEIMPROVE: 'Siteimprove',
|
||||
SOGOU_PIC_SPIDER: 'Sogou Pic Spider',
|
||||
SOGOU_WEB_SPIDER: 'Sogou web spider',
|
||||
STARTPAGE: 'Startpage',
|
||||
SURLY_BOT: 'SurdotlyBot',
|
||||
TIMPI_BOT: 'Timpibot',
|
||||
TOGETHER_BOT: 'Together-Bot',
|
||||
TURNITIN_BOT: 'TurnitinBot',
|
||||
TWIN_AGENT: 'TwinAgent',
|
||||
VERCEL_V0BOT: 'v0bot',
|
||||
WEBZIO: 'webzio',
|
||||
WEBZIO_EXTENDED: 'Webzio-Extended',
|
||||
WEBZIO_OMGILI: 'omgili',
|
||||
WEBZIO_OMGILI_BOT: 'omgilibot',
|
||||
XAI_BOT: 'xAI-Bot',
|
||||
YAHOO_JAPAN: 'Y!J-BRW',
|
||||
YAHOO_SLURP: 'Yahoo! Slurp',
|
||||
YANDEX_ACCESSIBILITY_BOT: 'YandexAccessibilityBot',
|
||||
YANDEX_ADDITIONAL_BOT: 'YandexAdditionalBot',
|
||||
YANDEX_ADNET: 'YandexAdNet',
|
||||
YANDEX_BLOGS: 'YandexBlogs',
|
||||
YANDEX_BOT: 'YandexBot',
|
||||
YANDEX_BOT_MIRRORDETECTOR: 'YandexBot MirrorDetector',
|
||||
YANDEX_COMBOT: 'YandexComBot',
|
||||
YANDEX_FAVICONS: 'YandexFavicons',
|
||||
YANDEX_IMAGE_RESIZER: 'YandexImageResizer',
|
||||
YANDEX_IMAGES: 'YandexImages',
|
||||
YANDEX_MARKET: 'YandexMarket',
|
||||
YANDEX_MEDIA: 'YandexMedia',
|
||||
YANDEX_METRIKA: 'YandexMetrika',
|
||||
YANDEX_MOBILE_BOT: 'YandexMobileBot',
|
||||
YANDEX_MOBILE_SCREENSHOT_BOT: 'YandexMobileScreenShotBot',
|
||||
YANDEX_NEWS: 'YandexNews',
|
||||
YANDEX_ONTODB: 'YandexOntoDB',
|
||||
YANDEX_ONTODB_API: 'YandexOntoDBAPI',
|
||||
YANDEX_PARTNER: 'YandexPartner',
|
||||
YANDEX_RCA: 'YandexRCA',
|
||||
YANDEX_RENDERRESOURCES_BOT: 'YandexRenderResourcesBot',
|
||||
YANDEX_SCREENSHOT_BOT: 'YandexScreenshotBot',
|
||||
YANDEX_SPRAV_BOT: 'YandexSpravBot',
|
||||
YANDEX_TRACKER: 'YandexTracker',
|
||||
YANDEX_VERTICALS: 'YandexVerticals',
|
||||
YANDEX_VERTIS: 'YandexVertis',
|
||||
YANDEX_VIDEO: 'YandexVideo',
|
||||
YANDEX_VIDEO_PARSER: 'YandexVideoParser',
|
||||
YANDEX_WEBMASTER: 'YandexWebmaster',
|
||||
YEP_BOT: 'YepBot',
|
||||
YETI: 'Yeti',
|
||||
YISOU_SPIDER: 'YisouSpider',
|
||||
YOU_BOT: 'YouBot',
|
||||
ZHIPU_CHATGLM_SPIDER: 'ChatGLM-Spider',
|
||||
ZUM_BOT: 'ZumBot'
|
||||
},
|
||||
Email: {
|
||||
AIRMAIL: 'Airmail',
|
||||
APPLE_MAIL: 'Mail',
|
||||
BLUEMAIL: 'BlueMail',
|
||||
DAUM_MAIL: 'DaumMail',
|
||||
EVOLUTION: 'Evolution',
|
||||
EM_CLIENT: 'eM Client',
|
||||
FOXMAIL: 'Foxmail',
|
||||
KMAIL: 'KMail',
|
||||
KMAIL2: 'kmail2',
|
||||
KONTACT: 'Kontact',
|
||||
MICROSOFT_OUTLOOK: 'Microsoft Outlook',
|
||||
MICROSOFT_OUTLOOK_MAC: 'MacOutlook',
|
||||
NAVER_MAILAPP: 'NaverMailApp',
|
||||
POLYMAIL: 'Polymail',
|
||||
PROTON_MAIL: 'ProtonMail',
|
||||
SPARK_MAIL: 'SparkDesktop',
|
||||
SPARROW: 'Sparrow',
|
||||
THUNDERBIRD: 'Thunderbird',
|
||||
YAHOO_MAIL: 'Yahoo',
|
||||
ZIMBRA: 'Zimbra',
|
||||
ZOHO_MAIL: 'ZohoMail-Desktop'
|
||||
},
|
||||
Fetcher: {
|
||||
AHREFS_SITEAUDIT: 'AhrefsSiteAudit',
|
||||
ANTHROPIC_CLAUDE_USER: 'Claude-User',
|
||||
ASANA: 'Asana',
|
||||
BETTER_UPTIME_BOT: 'Better Uptime Bot',
|
||||
BITLY_BOT: 'bitlybot',
|
||||
BLUESKY: 'Bluesky',
|
||||
BUFFER_LINKPREVIEWBOT: 'BufferLinkPreviewBot',
|
||||
COHERE_AI: 'Cohere-AI',
|
||||
DISCORD_BOT: 'Discordbot',
|
||||
DUCKDUCKGO_ASSISTBOT: 'DuckAssistBot',
|
||||
GOOGLE_CHROME_LIGHTHOUSE: 'Chrome-Lighthouse',
|
||||
GOOGLE_FEEDFETCHER: 'FeedFetcher-Google',
|
||||
GOOGLE_GEMINI_DEEP_RESEARCH: 'Gemini-Deep-Research',
|
||||
GOOGLE_IMAGEPROXY: 'GoogleImageProxy',
|
||||
GOOGLE_PAGERENDERER: 'Google-PageRenderer',
|
||||
GOOGLE_READ_ALOUD: 'Google-Read-Aloud',
|
||||
GOOGLE_PRODUCER: 'GoogleProducer',
|
||||
GOOGLE_SITE_VERIFICATION: 'Google-Site-Verification',
|
||||
HUBSPOT_PAGE_FETCHER: 'HubSpot Page Fetcher',
|
||||
IFRAMELY: 'Iframely',
|
||||
KAKAOTALK_SCRAP: 'kakaotalk-scrap',
|
||||
KEYBASE_BOT: 'KeybaseBot',
|
||||
META_EXTERNALFETCHER: 'meta-externalfetcher',
|
||||
META_WHATSAPP: 'WhatsApp',
|
||||
MICROSOFT_BINGPREVIEW: 'BingPreview',
|
||||
MICROSOFT_PREVIEW: 'MicrosoftPreview',
|
||||
MISTRALAI_USER: 'MistralAI-User',
|
||||
NAVER_BLUENO: 'Blueno',
|
||||
ONCRAWL_ROGERBOT: 'rogerbot',
|
||||
OPENAI_CHATGPT_USER: 'ChatGPT-User',
|
||||
PERPLEXITY_USER: 'Perplexity-User',
|
||||
PINTEREST_BOT: 'Pinterestbot',
|
||||
SEMRUSH_SITEAUDITBOT: 'SiteAuditBot',
|
||||
SLACK_BOT: 'Slackbot',
|
||||
SLACK_BOT_LINKEXPANDING: 'Slackbot-LinkExpanding',
|
||||
SLACK_IMGPROXY: 'Slack-ImgProxy',
|
||||
SNAP_URL_PREVIEW: 'Snap URL Preview',
|
||||
SKYPE_URIPREVIEW: 'SkypeUriPreview',
|
||||
TELEGRAM_BOT: 'TelegramBot',
|
||||
UPTIMEROBOT: 'UptimeRobot',
|
||||
VERCEL_FAVICON_BOT: 'vercel-favicon-bot',
|
||||
VERCEL_SCREENSHOT_BOT: 'vercel-screenshot-bot',
|
||||
VERCEL_BOT: 'Vercelbot',
|
||||
VERCEL_FLAGS: 'vercelflags',
|
||||
VERCEL_TRACING: 'verceltracing',
|
||||
X_TWITTERBOT: 'Twitterbot',
|
||||
YANDEX_CALENDAR: 'YandexCalendar',
|
||||
YANDEX_DIRECT: 'YandexDirect',
|
||||
YANDEX_DIRECTDYN: 'YandexDirectDyn',
|
||||
YANDEX_DIRECTFETCHER: 'YaDirectFetcher',
|
||||
YANDEX_FORDOMAIN: 'YandexForDomain',
|
||||
YANDEX_PAGECHECKER: 'YandexPagechecker',
|
||||
YANDEX_SEARCHSHOP: 'YandexSearchShop',
|
||||
YANDEX_SITELINKS: 'YandexSitelinks',
|
||||
YANDEX_USERPROXY: 'YandexUserproxy',
|
||||
ZOOMINFO_BOT: 'Zoombot'
|
||||
},
|
||||
InApp: {
|
||||
DISCORD: 'Discord',
|
||||
EVERNOTE: 'Evernote',
|
||||
FIGMA: 'Figma',
|
||||
FLIPBOARD: 'Flipboard',
|
||||
MATTERMOST: 'Mattermost',
|
||||
TEAMS: 'Teams',
|
||||
NOTION: 'Notion',
|
||||
POSTMAN: 'Postman',
|
||||
RAMBOX: 'Rambox',
|
||||
ROCKETCHAT: 'Rocket.Chat',
|
||||
SLACK: 'Slack',
|
||||
TIKTOK_LITE: 'TikTok Lite',
|
||||
VSCODE: 'VS Code',
|
||||
YAHOO_JAPAN: 'Yahoo! Japan'
|
||||
},
|
||||
Library: {
|
||||
ADOBE_AIR: 'AdobeAIR',
|
||||
AIOHTTP: 'aiohttp',
|
||||
APACHE_HTTPCLIENT: 'Apache-HttpClient',
|
||||
AXIOS: 'axios',
|
||||
GO_HTTP_CLIENT: 'go-http-client',
|
||||
GOT: 'got',
|
||||
GUZZLEHTTP: 'GuzzleHttp',
|
||||
JAVA: 'Java',
|
||||
JAVA_HTTPCLIENT: 'Java-http-client',
|
||||
JSDOM: 'jsdom',
|
||||
LIBWWW_PERL: 'libwww-perl',
|
||||
LUA_RESTY_HTTP: 'lua-resty-http',
|
||||
NEEDLE: 'Needle',
|
||||
NUTCH: 'Nutch',
|
||||
OKHTTP: 'OkHttp',
|
||||
NODE_FETCH: 'node-fetch',
|
||||
NODE_SUPERAGENT: 'node-superagent',
|
||||
PHP_SOAP: 'PHP-SOAP',
|
||||
POSTMAN_RUNTIME: 'PostmanRuntime',
|
||||
PYTHON_HTTPX: 'python-httpx',
|
||||
PYTHON_URLLIB: 'python-urllib',
|
||||
PYTHON_URLLIB3: 'python-urllib3',
|
||||
PYTHON_REQUESTS: 'python-requests',
|
||||
SCRAPY: 'Scrapy'
|
||||
}
|
||||
},
|
||||
DeviceVendor: {
|
||||
Vehicle: {
|
||||
BMW: 'BMW',
|
||||
BYD: 'BYD',
|
||||
JEEP: 'Jeep',
|
||||
RIVIAN: 'Rivian',
|
||||
TESLA: 'Tesla',
|
||||
VOLVO: 'Volvo'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
Browser,
|
||||
Browser,// deprecated
|
||||
CPU, // deprecated
|
||||
Device, // deprecated
|
||||
Vendor, // deprecated
|
||||
Engine, // deprecated
|
||||
OS, // deprecated
|
||||
BrowserName,
|
||||
BrowserType,
|
||||
CPU,
|
||||
Device,
|
||||
Vendor,
|
||||
Engine,
|
||||
OS
|
||||
CPUArch,
|
||||
DeviceType,
|
||||
DeviceVendor,
|
||||
EngineName,
|
||||
OSName,
|
||||
Extension
|
||||
};
|
||||
@@ -3,7 +3,7 @@
|
||||
// Source: /src/enums/ua-parser-enums.js
|
||||
|
||||
///////////////////////////////////////////////
|
||||
/* Enums for UAParser.js v2.0.4
|
||||
/* Enums for UAParser.js v2.0.6
|
||||
https://github.com/faisalman/ua-parser-js
|
||||
Author: Faisal Salman <f@faisalman.com>
|
||||
UAParser.js PRO Personal License */
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
/*jshint esversion: 6 */
|
||||
|
||||
const Browser = Object.freeze({
|
||||
const BrowserName = Object.freeze({
|
||||
'115': '115',
|
||||
'2345': '2345',
|
||||
'360': '360',
|
||||
@@ -24,6 +24,7 @@ const Browser = Object.freeze({
|
||||
AVG: 'AVG Secure Browser',
|
||||
BAIDU: 'Baidu Browser',
|
||||
BASILISK: 'Basilisk',
|
||||
BING: 'Bing',
|
||||
BLAZER: 'Blazer',
|
||||
BOLT: 'Bolt',
|
||||
BOWSER: 'Bowser',
|
||||
@@ -129,6 +130,7 @@ const Browser = Object.freeze({
|
||||
QUARK: 'Quark',
|
||||
QUPZILLA: 'QupZilla',
|
||||
QUTEBROWSER: 'qutebrowser',
|
||||
QWANT: 'Qwant',
|
||||
REKONQ: 'rekonq',
|
||||
ROCKMELT: 'Rockmelt',
|
||||
SAFARI: 'Safari',
|
||||
@@ -162,10 +164,15 @@ const Browser = Object.freeze({
|
||||
WEIBO: 'Weibo',
|
||||
WHALE: 'Whale',
|
||||
WOLVIC: 'Wolvic',
|
||||
YANDEX: 'Yandex'
|
||||
YANDEX: 'Yandex',
|
||||
ZALO: 'Zalo'
|
||||
|
||||
// TODO : test!
|
||||
});
|
||||
/**
|
||||
* @deprecated Use `BrowserName` instead
|
||||
*/
|
||||
const Browser = BrowserName;
|
||||
|
||||
const BrowserType = Object.freeze({
|
||||
CRAWLER: 'crawler',
|
||||
@@ -177,8 +184,9 @@ const BrowserType = Object.freeze({
|
||||
LIBRARY: 'library'
|
||||
});
|
||||
|
||||
const CPU = Object.freeze({
|
||||
const CPUArch = Object.freeze({
|
||||
'68K': '68k',
|
||||
ALPHA: 'alpha',
|
||||
ARM : 'arm',
|
||||
ARM_64: 'arm64',
|
||||
ARM_HF: 'armhf',
|
||||
@@ -196,8 +204,12 @@ const CPU = Object.freeze({
|
||||
X86: 'ia32',
|
||||
X86_64: 'amd64'
|
||||
});
|
||||
/**
|
||||
* @deprecated Use `CPUArch` instead
|
||||
*/
|
||||
const CPU = CPUArch;
|
||||
|
||||
const Device = Object.freeze({
|
||||
const DeviceType = Object.freeze({
|
||||
CONSOLE: 'console',
|
||||
DESKTOP: 'desktop',
|
||||
EMBEDDED: 'embedded',
|
||||
@@ -207,8 +219,12 @@ const Device = Object.freeze({
|
||||
WEARABLE: 'wearable',
|
||||
XR: 'xr'
|
||||
});
|
||||
/**
|
||||
* @deprecated Use `DeviceType` instead
|
||||
*/
|
||||
const Device = DeviceType;
|
||||
|
||||
const Vendor = Object.freeze({
|
||||
const DeviceVendor = Object.freeze({
|
||||
ACER: 'Acer',
|
||||
ADVAN: 'Advan',
|
||||
ALCATEL: 'Alcatel',
|
||||
@@ -229,6 +245,7 @@ const Vendor = Object.freeze({
|
||||
GEEKSPHONE: 'GeeksPhone',
|
||||
GENERIC: 'Generic',
|
||||
GOOGLE: 'Google',
|
||||
HISENSE: 'Hisense',
|
||||
HMD: 'HMD',
|
||||
HP: 'HP',
|
||||
HTC: 'HTC',
|
||||
@@ -256,6 +273,7 @@ const Vendor = Object.freeze({
|
||||
PALM: 'Palm',
|
||||
PANASONIC: 'Panasonic',
|
||||
PEBBLE: 'Pebble',
|
||||
PHILIPS: 'Philips',
|
||||
PICO: 'Pico',
|
||||
POLYTRON: 'Polytron',
|
||||
REALME: 'Realme',
|
||||
@@ -270,12 +288,13 @@ const Vendor = Object.freeze({
|
||||
SPRINT: 'Sprint',
|
||||
TCL: 'TCL',
|
||||
TECHNISAT: 'TechniSAT',
|
||||
TECNO: 'Tecno',
|
||||
TECNO: 'TECNO',
|
||||
TESLA: 'Tesla',
|
||||
ULEFONE: 'Ulefone',
|
||||
VIVO: 'Vivo',
|
||||
VIZIO: 'Vizio',
|
||||
VODAFONE: 'Vodafone',
|
||||
WIKO: 'Wiko',
|
||||
XBOX: 'Xbox',
|
||||
XIAOMI: 'Xiaomi',
|
||||
ZEBRA: 'Zebra',
|
||||
@@ -283,8 +302,12 @@ const Vendor = Object.freeze({
|
||||
|
||||
// TODO : test!
|
||||
});
|
||||
/**
|
||||
* @deprecated Use `DeviceVendor` instead
|
||||
*/
|
||||
const Vendor = DeviceVendor;
|
||||
|
||||
const Engine = Object.freeze({
|
||||
const EngineName = Object.freeze({
|
||||
AMAYA: 'Amaya',
|
||||
ARKWEB: 'ArkWeb',
|
||||
BLINK: 'Blink',
|
||||
@@ -306,8 +329,12 @@ const Engine = Object.freeze({
|
||||
W3M: 'w3m',
|
||||
WEBKIT: 'WebKit'
|
||||
});
|
||||
/**
|
||||
* @deprecated Use `EngineName` instead
|
||||
*/
|
||||
const Engine = EngineName;
|
||||
|
||||
const OS = Object.freeze({
|
||||
const OSName = Object.freeze({
|
||||
AIX: 'AIX',
|
||||
AMIGA_OS: 'Amiga OS',
|
||||
ANDROID: 'Android',
|
||||
@@ -403,13 +430,331 @@ const OS = Object.freeze({
|
||||
|
||||
// TODO : test!
|
||||
});
|
||||
/**
|
||||
* @deprecated Use `OSName` instead
|
||||
*/
|
||||
const OS = OSName;
|
||||
|
||||
/*////////////////////////////////
|
||||
* Enums for Extensions submodule
|
||||
*///////////////////////////////
|
||||
|
||||
const Extension = Object.freeze({
|
||||
BrowserName: {
|
||||
CLI: {
|
||||
CURL: 'curl',
|
||||
ELINKS: 'ELinks',
|
||||
HTTPIE: 'HTTPie',
|
||||
LYNX: 'Lynx',
|
||||
WGET: 'Wget'
|
||||
},
|
||||
Crawler: {
|
||||
AHREFS_BOT: 'AhrefsBot',
|
||||
AI2_BOT: 'AI2Bot',
|
||||
AIHIT_BOT: 'aiHitBot',
|
||||
ALGOLIA_CRAWLER: 'Algolia Crawler',
|
||||
APPLE_BOT: 'Applebot',
|
||||
APPLE_BOT_EXTENDED: 'Applebot-Extended',
|
||||
ASK_TEOMA: 'Teoma',
|
||||
AMAZON_BOT: 'Amazonbot',
|
||||
AMAZON_CONTXBOT: 'contxbot',
|
||||
ANTHROPIC_AI: 'anthropic-ai',
|
||||
ANTHROPIC_CLAUDE_BOT: 'ClaudeBot',
|
||||
ANTHROPIC_CLAUDE_SEARCHBOT: 'Claude-SearchBot',
|
||||
ANTHROPIC_CLAUDE_WEB: 'Claude-Web',
|
||||
ARCHIVEORG_BOT: 'archive.org_bot',
|
||||
BAIDU_ADS: 'Baidu-ADS',
|
||||
BAIDU_SPIDER: 'Baiduspider',
|
||||
BAIDU_SPIDER_ADS: 'Baiduspider-ads',
|
||||
BAIDU_SPIDER_CPRO: 'Baiduspider-cpro',
|
||||
BAIDU_SPIDER_FAVO: 'Baiduspider-favo',
|
||||
BAIDU_SPIDER_IMAGE: 'Baiduspider-image',
|
||||
BAIDU_SPIDER_NEWS: 'Baiduspider-news',
|
||||
BAIDU_SPIDER_RENDER: 'Baiduspider-render',
|
||||
BAIDU_SPIDER_VIDEO: 'Baiduspider-video',
|
||||
BLEX_BOT: 'BLEXBot',
|
||||
BOTIFY: 'botify',
|
||||
BRAVE_BOT: 'Bravebot',
|
||||
BYTEDANCE_BYTESPIDER: 'Bytespider',
|
||||
BYTEDANCE_TIKTOKSPIDER: 'TikTokSpider',
|
||||
COMMON_CRAWL_CCBOT: 'CCBot',
|
||||
COCCOC_BOT_WEB: 'coccocbot-web',
|
||||
COCCOC_BOT_IMAGE: 'coccocbot-image',
|
||||
COHERE_TRAINING_DATA_CRAWLER: 'cohere-training-data-crawler',
|
||||
COTOYOGI: 'Cotoyogi',
|
||||
COVEO_BOT: 'Coveobot',
|
||||
CRITEO_BOT: 'CriteoBot',
|
||||
DATAFORSEO_BOT: 'DataForSeoBot',
|
||||
DAUM: 'Daum',
|
||||
DAUM_DAUMOA: 'Daumoa',
|
||||
DAUM_DAUMOA_IMAGE: 'Daumoa-image',
|
||||
DEEPSEEK_BOT: 'DeepSeekBot',
|
||||
DIFFBOT: 'Diffbot',
|
||||
DUCKDUCKGO_BOT: 'DuckDuckBot',
|
||||
DUCKDUCKGO_FAVICONS_BOT: 'DuckDuckGo-Favicons-Bot',
|
||||
ELASTIC: 'Elastic',
|
||||
ELASTIC_SWIFTYPE_BOT: 'Swiftbot',
|
||||
EXALEAD_EXABOT: 'Exabot',
|
||||
FIRECRAWL_AGENT: 'FirecrawlAgent',
|
||||
FREESPOKE: 'Freespoke',
|
||||
GOOGLE_ADSBOT: 'AdsBot-Google',
|
||||
GOOGLE_ADSBOT_MOBILE: 'Adsbot-Google-Mobile',
|
||||
GOOGLE_ADSENSE: 'AdSense',
|
||||
GOOGLE_APIS: 'APIs-Google',
|
||||
GOOGLE_BOT: 'Googlebot',
|
||||
GOOGLE_BOT_IMAGE: 'Googlebot-Image',
|
||||
GOOGLE_BOT_NEWS: 'Googlebot-News',
|
||||
GOOGLE_BOT_VIDEO: 'Googlebot-Video',
|
||||
GOOGLE_CLOUDVERTEXBOT: 'Google-CloudVertexBot',
|
||||
GOOGLE_EXTENDED: 'Google-Extended',
|
||||
GOOGLE_INSPECTIONTOOL: 'Google-InspectionTool',
|
||||
GOOGLE_OTHER: 'GoogleOther',
|
||||
GOOGLE_OTHER_IMAGE: 'GoogleOther-Image',
|
||||
GOOGLE_OTHER_VIDEO: 'GoogleOther-Video',
|
||||
GOOGLE_SAFETY: 'Google-Safety',
|
||||
GOOGLE_STOREBOT: 'Storebot-Google',
|
||||
HIVE_IMAGESIFTBOT: 'ImagesiftBot',
|
||||
HUAWEI_PANGUBOT: 'PanguBot',
|
||||
HUAWEI_PETALBOT: 'PetalBot',
|
||||
HUGGINGFACE_BOT: 'HuggingFace-Bot',
|
||||
HUNTER_VELENPUBLICWEBCRAWLER: 'VelenPublicWebCrawler',
|
||||
IA_ARCHIVER: 'ia_archiver',
|
||||
IASK_BOT: 'iAskBot',
|
||||
KAGI_BOT: 'Kagibot',
|
||||
KANGAROO_BOT: 'Kangaroo Bot',
|
||||
LINE_SPIDER: 'Linespider',
|
||||
LINKEDIN_BOT: 'LinkedInBot',
|
||||
MAGPIE_CRAWLER: 'magpie-crawler',
|
||||
MARGINALIA: 'marginalia',
|
||||
META_EXTERNALAGENT: 'meta-externalagent',
|
||||
META_FACEBOOKBOT: 'FacebookBot',
|
||||
META_FACEBOOKCATALOG: 'facebookcatalog',
|
||||
META_FACEBOOKEXTERNALHIT: 'facebookexternalhit',
|
||||
MAJESTIC_MJ12BOT: 'MJ12bot',
|
||||
MICROSOFT_BINGBOT: 'Bingbot',
|
||||
MICROSOFT_MSNBOT: 'msnbot',
|
||||
MICROSOFT_ADIDXBOT: 'adidxbot',
|
||||
MOJEEK_BOT: 'MojeekBot',
|
||||
MOZ_DOTBOT: 'DotBot',
|
||||
ONCRAWL: 'OnCrawl',
|
||||
ONESPOT_SCRAPERBOT: 'Onespot-ScraperBot',
|
||||
OPENAI_GPTBOT: 'GPTBot',
|
||||
OPENAI_SEARCH_BOT: 'OAI-SearchBot',
|
||||
PERPLEXITY_BOT: 'PerplexityBot',
|
||||
QIHOO_360_SPIDER: '360Spider',
|
||||
QWANT_BOT: 'Qwantbot',
|
||||
QWANT_BOT_NEWS: 'Qwantbot-news',
|
||||
REPLICATE_BOT: 'Replicate-Bot',
|
||||
RUNPOD_BOT: 'RunPod-Bot',
|
||||
SB_INTUITIONS_BOT: 'SBIntuitionsBot',
|
||||
SEEKPORT_BOT: 'SeekportBot',
|
||||
SEMRUSH_BOT: 'SemrushBot',
|
||||
SEMRUSH_BOT_BACKLINK: 'SemrushBot-BA',
|
||||
SEMRUSH_BOT_CONTENTSHAKE: 'SemrushBot-OCOB',
|
||||
SEMRUSH_BOT_SEO_CHECKER: 'SemrushBot-SI',
|
||||
SEZNAM_BOT: 'SeznamBot',
|
||||
SITEIMPROVE: 'Siteimprove',
|
||||
SOGOU_PIC_SPIDER: 'Sogou Pic Spider',
|
||||
SOGOU_WEB_SPIDER: 'Sogou web spider',
|
||||
STARTPAGE: 'Startpage',
|
||||
SURLY_BOT: 'SurdotlyBot',
|
||||
TIMPI_BOT: 'Timpibot',
|
||||
TOGETHER_BOT: 'Together-Bot',
|
||||
TURNITIN_BOT: 'TurnitinBot',
|
||||
TWIN_AGENT: 'TwinAgent',
|
||||
VERCEL_V0BOT: 'v0bot',
|
||||
WEBZIO: 'webzio',
|
||||
WEBZIO_EXTENDED: 'Webzio-Extended',
|
||||
WEBZIO_OMGILI: 'omgili',
|
||||
WEBZIO_OMGILI_BOT: 'omgilibot',
|
||||
XAI_BOT: 'xAI-Bot',
|
||||
YAHOO_JAPAN: 'Y!J-BRW',
|
||||
YAHOO_SLURP: 'Yahoo! Slurp',
|
||||
YANDEX_ACCESSIBILITY_BOT: 'YandexAccessibilityBot',
|
||||
YANDEX_ADDITIONAL_BOT: 'YandexAdditionalBot',
|
||||
YANDEX_ADNET: 'YandexAdNet',
|
||||
YANDEX_BLOGS: 'YandexBlogs',
|
||||
YANDEX_BOT: 'YandexBot',
|
||||
YANDEX_BOT_MIRRORDETECTOR: 'YandexBot MirrorDetector',
|
||||
YANDEX_COMBOT: 'YandexComBot',
|
||||
YANDEX_FAVICONS: 'YandexFavicons',
|
||||
YANDEX_IMAGE_RESIZER: 'YandexImageResizer',
|
||||
YANDEX_IMAGES: 'YandexImages',
|
||||
YANDEX_MARKET: 'YandexMarket',
|
||||
YANDEX_MEDIA: 'YandexMedia',
|
||||
YANDEX_METRIKA: 'YandexMetrika',
|
||||
YANDEX_MOBILE_BOT: 'YandexMobileBot',
|
||||
YANDEX_MOBILE_SCREENSHOT_BOT: 'YandexMobileScreenShotBot',
|
||||
YANDEX_NEWS: 'YandexNews',
|
||||
YANDEX_ONTODB: 'YandexOntoDB',
|
||||
YANDEX_ONTODB_API: 'YandexOntoDBAPI',
|
||||
YANDEX_PARTNER: 'YandexPartner',
|
||||
YANDEX_RCA: 'YandexRCA',
|
||||
YANDEX_RENDERRESOURCES_BOT: 'YandexRenderResourcesBot',
|
||||
YANDEX_SCREENSHOT_BOT: 'YandexScreenshotBot',
|
||||
YANDEX_SPRAV_BOT: 'YandexSpravBot',
|
||||
YANDEX_TRACKER: 'YandexTracker',
|
||||
YANDEX_VERTICALS: 'YandexVerticals',
|
||||
YANDEX_VERTIS: 'YandexVertis',
|
||||
YANDEX_VIDEO: 'YandexVideo',
|
||||
YANDEX_VIDEO_PARSER: 'YandexVideoParser',
|
||||
YANDEX_WEBMASTER: 'YandexWebmaster',
|
||||
YEP_BOT: 'YepBot',
|
||||
YETI: 'Yeti',
|
||||
YISOU_SPIDER: 'YisouSpider',
|
||||
YOU_BOT: 'YouBot',
|
||||
ZHIPU_CHATGLM_SPIDER: 'ChatGLM-Spider',
|
||||
ZUM_BOT: 'ZumBot'
|
||||
},
|
||||
Email: {
|
||||
AIRMAIL: 'Airmail',
|
||||
APPLE_MAIL: 'Mail',
|
||||
BLUEMAIL: 'BlueMail',
|
||||
DAUM_MAIL: 'DaumMail',
|
||||
EVOLUTION: 'Evolution',
|
||||
EM_CLIENT: 'eM Client',
|
||||
FOXMAIL: 'Foxmail',
|
||||
KMAIL: 'KMail',
|
||||
KMAIL2: 'kmail2',
|
||||
KONTACT: 'Kontact',
|
||||
MICROSOFT_OUTLOOK: 'Microsoft Outlook',
|
||||
MICROSOFT_OUTLOOK_MAC: 'MacOutlook',
|
||||
NAVER_MAILAPP: 'NaverMailApp',
|
||||
POLYMAIL: 'Polymail',
|
||||
PROTON_MAIL: 'ProtonMail',
|
||||
SPARK_MAIL: 'SparkDesktop',
|
||||
SPARROW: 'Sparrow',
|
||||
THUNDERBIRD: 'Thunderbird',
|
||||
YAHOO_MAIL: 'Yahoo',
|
||||
ZIMBRA: 'Zimbra',
|
||||
ZOHO_MAIL: 'ZohoMail-Desktop'
|
||||
},
|
||||
Fetcher: {
|
||||
AHREFS_SITEAUDIT: 'AhrefsSiteAudit',
|
||||
ANTHROPIC_CLAUDE_USER: 'Claude-User',
|
||||
ASANA: 'Asana',
|
||||
BETTER_UPTIME_BOT: 'Better Uptime Bot',
|
||||
BITLY_BOT: 'bitlybot',
|
||||
BLUESKY: 'Bluesky',
|
||||
BUFFER_LINKPREVIEWBOT: 'BufferLinkPreviewBot',
|
||||
COHERE_AI: 'Cohere-AI',
|
||||
DISCORD_BOT: 'Discordbot',
|
||||
DUCKDUCKGO_ASSISTBOT: 'DuckAssistBot',
|
||||
GOOGLE_CHROME_LIGHTHOUSE: 'Chrome-Lighthouse',
|
||||
GOOGLE_FEEDFETCHER: 'FeedFetcher-Google',
|
||||
GOOGLE_GEMINI_DEEP_RESEARCH: 'Gemini-Deep-Research',
|
||||
GOOGLE_IMAGEPROXY: 'GoogleImageProxy',
|
||||
GOOGLE_PAGERENDERER: 'Google-PageRenderer',
|
||||
GOOGLE_READ_ALOUD: 'Google-Read-Aloud',
|
||||
GOOGLE_PRODUCER: 'GoogleProducer',
|
||||
GOOGLE_SITE_VERIFICATION: 'Google-Site-Verification',
|
||||
HUBSPOT_PAGE_FETCHER: 'HubSpot Page Fetcher',
|
||||
IFRAMELY: 'Iframely',
|
||||
KAKAOTALK_SCRAP: 'kakaotalk-scrap',
|
||||
KEYBASE_BOT: 'KeybaseBot',
|
||||
META_EXTERNALFETCHER: 'meta-externalfetcher',
|
||||
META_WHATSAPP: 'WhatsApp',
|
||||
MICROSOFT_BINGPREVIEW: 'BingPreview',
|
||||
MICROSOFT_PREVIEW: 'MicrosoftPreview',
|
||||
MISTRALAI_USER: 'MistralAI-User',
|
||||
NAVER_BLUENO: 'Blueno',
|
||||
ONCRAWL_ROGERBOT: 'rogerbot',
|
||||
OPENAI_CHATGPT_USER: 'ChatGPT-User',
|
||||
PERPLEXITY_USER: 'Perplexity-User',
|
||||
PINTEREST_BOT: 'Pinterestbot',
|
||||
SEMRUSH_SITEAUDITBOT: 'SiteAuditBot',
|
||||
SLACK_BOT: 'Slackbot',
|
||||
SLACK_BOT_LINKEXPANDING: 'Slackbot-LinkExpanding',
|
||||
SLACK_IMGPROXY: 'Slack-ImgProxy',
|
||||
SNAP_URL_PREVIEW: 'Snap URL Preview',
|
||||
SKYPE_URIPREVIEW: 'SkypeUriPreview',
|
||||
TELEGRAM_BOT: 'TelegramBot',
|
||||
UPTIMEROBOT: 'UptimeRobot',
|
||||
VERCEL_FAVICON_BOT: 'vercel-favicon-bot',
|
||||
VERCEL_SCREENSHOT_BOT: 'vercel-screenshot-bot',
|
||||
VERCEL_BOT: 'Vercelbot',
|
||||
VERCEL_FLAGS: 'vercelflags',
|
||||
VERCEL_TRACING: 'verceltracing',
|
||||
X_TWITTERBOT: 'Twitterbot',
|
||||
YANDEX_CALENDAR: 'YandexCalendar',
|
||||
YANDEX_DIRECT: 'YandexDirect',
|
||||
YANDEX_DIRECTDYN: 'YandexDirectDyn',
|
||||
YANDEX_DIRECTFETCHER: 'YaDirectFetcher',
|
||||
YANDEX_FORDOMAIN: 'YandexForDomain',
|
||||
YANDEX_PAGECHECKER: 'YandexPagechecker',
|
||||
YANDEX_SEARCHSHOP: 'YandexSearchShop',
|
||||
YANDEX_SITELINKS: 'YandexSitelinks',
|
||||
YANDEX_USERPROXY: 'YandexUserproxy',
|
||||
ZOOMINFO_BOT: 'Zoombot'
|
||||
},
|
||||
InApp: {
|
||||
DISCORD: 'Discord',
|
||||
EVERNOTE: 'Evernote',
|
||||
FIGMA: 'Figma',
|
||||
FLIPBOARD: 'Flipboard',
|
||||
MATTERMOST: 'Mattermost',
|
||||
TEAMS: 'Teams',
|
||||
NOTION: 'Notion',
|
||||
POSTMAN: 'Postman',
|
||||
RAMBOX: 'Rambox',
|
||||
ROCKETCHAT: 'Rocket.Chat',
|
||||
SLACK: 'Slack',
|
||||
TIKTOK_LITE: 'TikTok Lite',
|
||||
VSCODE: 'VS Code',
|
||||
YAHOO_JAPAN: 'Yahoo! Japan'
|
||||
},
|
||||
Library: {
|
||||
ADOBE_AIR: 'AdobeAIR',
|
||||
AIOHTTP: 'aiohttp',
|
||||
APACHE_HTTPCLIENT: 'Apache-HttpClient',
|
||||
AXIOS: 'axios',
|
||||
GO_HTTP_CLIENT: 'go-http-client',
|
||||
GOT: 'got',
|
||||
GUZZLEHTTP: 'GuzzleHttp',
|
||||
JAVA: 'Java',
|
||||
JAVA_HTTPCLIENT: 'Java-http-client',
|
||||
JSDOM: 'jsdom',
|
||||
LIBWWW_PERL: 'libwww-perl',
|
||||
LUA_RESTY_HTTP: 'lua-resty-http',
|
||||
NEEDLE: 'Needle',
|
||||
NUTCH: 'Nutch',
|
||||
OKHTTP: 'OkHttp',
|
||||
NODE_FETCH: 'node-fetch',
|
||||
NODE_SUPERAGENT: 'node-superagent',
|
||||
PHP_SOAP: 'PHP-SOAP',
|
||||
POSTMAN_RUNTIME: 'PostmanRuntime',
|
||||
PYTHON_HTTPX: 'python-httpx',
|
||||
PYTHON_URLLIB: 'python-urllib',
|
||||
PYTHON_URLLIB3: 'python-urllib3',
|
||||
PYTHON_REQUESTS: 'python-requests',
|
||||
SCRAPY: 'Scrapy'
|
||||
}
|
||||
},
|
||||
DeviceVendor: {
|
||||
Vehicle: {
|
||||
BMW: 'BMW',
|
||||
BYD: 'BYD',
|
||||
JEEP: 'Jeep',
|
||||
RIVIAN: 'Rivian',
|
||||
TESLA: 'Tesla',
|
||||
VOLVO: 'Volvo'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export {
|
||||
Browser,
|
||||
Browser,// deprecated
|
||||
CPU, // deprecated
|
||||
Device, // deprecated
|
||||
Vendor, // deprecated
|
||||
Engine, // deprecated
|
||||
OS, // deprecated
|
||||
BrowserName,
|
||||
BrowserType,
|
||||
CPU,
|
||||
Device,
|
||||
Vendor,
|
||||
Engine,
|
||||
OS
|
||||
CPUArch,
|
||||
DeviceType,
|
||||
DeviceVendor,
|
||||
EngineName,
|
||||
OSName,
|
||||
Extension
|
||||
};
|
||||
2
src/extensions/ua-parser-extensions.d.ts
vendored
2
src/extensions/ua-parser-extensions.d.ts
vendored
@@ -1,4 +1,4 @@
|
||||
// Type definitions for Helpers submodule of UAParser.js v2.0.4
|
||||
// Type definitions for Helpers submodule of UAParser.js v2.0.5
|
||||
// Project: https://github.com/faisalman/ua-parser-js
|
||||
// Definitions by: Faisal Salman <https://github.com/faisalman>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////
|
||||
/* Extensions for UAParser.js v2.0.4
|
||||
/* Extensions for UAParser.js v2.0.6
|
||||
https://github.com/faisalman/ua-parser-js
|
||||
Author: Faisal Salman <f@faisalman.com>
|
||||
UAParser.js PRO Personal License */
|
||||
@@ -43,20 +43,33 @@ const Crawlers = Object.freeze({
|
||||
// AhrefsBot - https://ahrefs.com/robot
|
||||
// Amazonbot - https://developer.amazon.com/amazonbot
|
||||
// Bingbot / AdIdxBot - https://www.bing.com/webmasters/help/which-crawlers-does-bing-use-8c184ec0
|
||||
// Bravebot - https://search.brave.com/help/brave-search-crawler
|
||||
// CCBot - https://commoncrawl.org/faq
|
||||
// contxbot - https://affiliate-program.amazon.com/help/node/topic/GT98G5PPRERNVZ2C
|
||||
// Coveobot - https://connect.coveo.com/s/article/19648
|
||||
// CriteoBot - https://www.criteo.com/criteo-crawler/
|
||||
// Dotbot - https://moz.com/help/moz-procedures/crawlers/dotbot
|
||||
// DuckDuckBot - http://duckduckgo.com/duckduckbot.html
|
||||
// FacebookBot - https://developers.facebook.com/docs/sharing/bot/
|
||||
// GPTBot - https://platform.openai.com/docs/gptbot
|
||||
// iAskBot - https://iask.ai
|
||||
// Kagibot - https://kagi.com/bot
|
||||
// Kangaroo Bot - https://kangaroollm.com.au/kangaroo-bot/
|
||||
// LinkedInBot - http://www.linkedin.com
|
||||
// MJ12bot - https://mj12bot.com/
|
||||
// MojeekBot - https://www.mojeek.com/bot.html
|
||||
// Onespot - https://www.onespot.com/identifying-traffic.html
|
||||
// OpenAI's SearchGPT - https://platform.openai.com/docs/bots
|
||||
// PerplexityBot - https://perplexity.ai/perplexitybot
|
||||
// SBIntuitionsBot - https://www.sbintuitions.co.jp/bot/
|
||||
// SeznamBot - http://napoveda.seznam.cz/seznambot-intro
|
||||
/((?:adidx|ahrefs|amazon|bing|cc|dot|duckduck|exa|facebook|gpt|iask|linkedin|mj12|mojeek|oai-search|onespot-scraper|perplexity|semrush|seznam)bot)\/([\w\.-]+)/i,
|
||||
// SurdotlyBot - http://sur.ly/bot.html
|
||||
// Swiftbot - https://swiftype.com/swiftbot
|
||||
// YepBot - https://yep.com/yepbot/
|
||||
/((?:adidx|ahrefs|amazon|bing|brave|cc|contx|coveo|criteo|dot|duckduck(?:go-favicons-)?|exa|facebook|gpt|iask|kagi|kangaroo |linkedin|mj12|mojeek|oai-search|onespot-scraper|perplexity|sbintuitions|semrush|seznam|surdotly|swift|yep)bot)\/([\w\.-]+)/i,
|
||||
|
||||
// Algolia Crawler
|
||||
/(algolia crawler(?: renderscript)?)\/?([\w\.]*)/i,
|
||||
|
||||
// Applebot - http://apple.com/go/applebot
|
||||
/(applebot(?:-extended)?)\/?([\w\.]*)/i,
|
||||
@@ -65,7 +78,7 @@ const Crawlers = Object.freeze({
|
||||
/(baiduspider[-imagevdonwsfcpr]{0,7})\/?([\w\.]*)/i,
|
||||
|
||||
// ClaudeBot (Anthropic)
|
||||
/(claude(?:bot|-web)|anthropic-ai)\/?([\w\.]*)/i,
|
||||
/(claude(?:bot|-searchbot|-web)|anthropic-ai)\/?([\w\.]*)/i,
|
||||
|
||||
// Coc Coc Bot - https://help.coccoc.com/en/search-engine
|
||||
/(coccocbot-(?:image|web))\/([\w\.]+)/i,
|
||||
@@ -83,8 +96,11 @@ const Crawlers = Object.freeze({
|
||||
// Internet Archive (archive.org)
|
||||
/(ia_archiver|archive\.org_bot)\/?([\w\.]*)/i,
|
||||
|
||||
// OnCrawl
|
||||
/(oncrawl) mobile\/([\w\.]+)/i,
|
||||
|
||||
// Qwantbot - https://help.qwant.com/bot
|
||||
/(qwantbot)[-\w]*\/?([\w\.]*)/i,
|
||||
/(qwantbot(?:-news)?)[-\w]*\/?([\w\.]*)/i,
|
||||
|
||||
// SemrushBot - http://www.semrush.com/bot.html
|
||||
/((?:semrush|splitsignal)bot[-abcfimostw]*)\/?([\w\.-]*)/i,
|
||||
@@ -96,30 +112,38 @@ const Crawlers = Object.freeze({
|
||||
/(y!?j-(?:asr|br[uw]|dscv|mmp|vsidx|wsc))\/([\w\.]+)/i,
|
||||
|
||||
// Yandex Bots - https://yandex.com/bots
|
||||
/(yandex(?:(?:mobile)?(?:accessibility|additional|renderresources|screenshot|sprav)?bot|image(?:s|resizer)|video(?:parser)?|blogs|adnet|favicons|fordomain|market|media|metrika|news|ontodb(?:api)?|pagechecker|partner|rca|tracker|turbo|vertis|webmaster|antivirus))\/([\w\.]+)/i,
|
||||
/(yandex(?:(?:mobile)?(?:accessibility|additional|com|renderresources|screenshot|sprav)?bot(?!.+mirror)|image(?:s|resizer)|adnet|blogs|favicons|market|media|metrika|news|ontodb(?:api)?|partner|rca|tracker|turbo|verti(?:cal)?s|webmaster|video(?:parser)?))\/([\w\.]+)/i,
|
||||
|
||||
// Yeti (Naver)
|
||||
/(yeti)\/([\w\.]+)/i,
|
||||
|
||||
// aiHitBot / Diffbot / Linespider / Magpie-Crawler / Omgilibot / OpenAI Image Downloader / Webzio-Extended / Screaming Frog SEO Spider / Startpage / Timpibot / VelenPublicWebCrawler / YisouSpider / YouBot
|
||||
/((?:aihit|diff|timpi|you)bot|omgili(?:bot)?|openai image downloader|(?:magpie-|velenpublicweb)crawler|startpageprivateimageproxy|webzio-extended|(?:chatglm-|line|screaming frog seo |yisou)spider)\/?([\w\.]*)/i
|
||||
// aiHitBot / Algolia Crawler / BLEXBot / Diffbot / FirecrawlAgent / HuggingFace-Bot / Linespider / MSNBot / Magpie-Crawler / Omgilibot / OpenAI Image Downloader / PanguBot / Replicate-Bot / RunPod-Bot / Webzio-Extended / Screaming Frog SEO Spider / Startpage / Timpibot / Together-Bot / VelenPublicWebCrawler / xAI-Bot / YisouSpider / YouBot / ZumBot
|
||||
// Cotoyogi - https://ds.rois.ac.jp/en_center8/en_crawler/
|
||||
// Freespoke - https://docs.freespoke.com/search/bot/
|
||||
/((?:aihit|blex|diff|huggingface-|msn|pangu|replicate-|runpod-|timpi|together-|xai-|you|zum)bot|(?:magpie-|velenpublicweb)crawler|(?:chatglm-|line|screaming frog seo |yisou)spider|cotoyogi|firecrawlagent|freespoke|omgili(?:bot)?|openai image downloader|startpageprivateimageproxy|twinagent|webzio-extended)\/?([\w\.]*)/i
|
||||
],
|
||||
|
||||
[NAME, VERSION, [TYPE, CRAWLER]],
|
||||
|
||||
[
|
||||
// YandexBot MirrorDetector
|
||||
/(yandexbot\/([\w\.]+); mirrordetector)/i
|
||||
],
|
||||
[[NAME, /\/.+;/ig, ''], VERSION, [TYPE, CRAWLER]],
|
||||
|
||||
[
|
||||
// Google Bots
|
||||
/((?:adsbot|apis|mediapartners)-google(?:-mobile)?|google-?(?:other|cloudvertexbot|extended|safety))/i,
|
||||
|
||||
// AI2Bot - https://allenai.org/crawler
|
||||
// Bytespider
|
||||
// DataForSeoBot - https://dataforseo.com/dataforseo-bot
|
||||
// Huawei AspiegelBot / PetalBot https://aspiegel.com/petalbot
|
||||
// ImagesiftBot - https://imagesift.com/about
|
||||
// Qihoo 360Spider
|
||||
// Siteimprove - https://help.siteimprove.com/support/solutions/articles/80000448553
|
||||
// TurnitinBot - https://www.turnitin.com/robot/crawlerinfo.html
|
||||
// v0bot - https://vercel.com/docs/bot-management
|
||||
// Yahoo! Slurp - http://help.yahoo.com/help/us/ysearch/slurp
|
||||
/\b(360spider-?(?:image|video)?|bytespider|(?:ai2|aspiegel|dataforseo|imagesift|petal|turnitin)bot|teoma|yahoo! slurp)/i
|
||||
// Botify / Bytespider / DeepSeekBot / Qihoo 360Spider / SeekportBot / TikTokSpider
|
||||
/\b((ai2|aspiegel|dataforseo|deepseek|imagesift|petal|seekport|turnitin|v0)bot|360spider-?(image|video)?|baidu-ads|botify|(byte|tiktok)spider|cohere-training-data-crawler|elastic(?=\/s)|marginalia|siteimprove(?=bot|\.com)|teoma|webzio|yahoo! slurp)/i
|
||||
],
|
||||
[NAME, [TYPE, CRAWLER]]
|
||||
]
|
||||
@@ -234,16 +258,17 @@ const Emails = Object.freeze({
|
||||
const Fetchers = Object.freeze({
|
||||
browser : [
|
||||
[
|
||||
// Asana / Bitlybot / Better Uptime / BingPreview / Blueno / Cohere-AI / HubSpot Page Fetcher / kakaotalk-scrap / Mastodon / MicrosoftPreview / Pinterestbot / Redditbot / Rogerbot / SiteAuditBot / Telegrambot / Twitterbot / UptimeRobot
|
||||
// AhrefsSiteAudit - https://ahrefs.com/robot/site-audit
|
||||
// Buffer Link Preview Bot - https://scraper.buffer.com/about/bots/link-preview-bot
|
||||
// ChatGPT-User - https://platform.openai.com/docs/plugins/bot
|
||||
// DuckAssistBot - https://duckduckgo.com/duckassistbot/
|
||||
// Better Uptime / BingPreview / Mastodon / MicrosoftPreview / Pinterestbot / Redditbot / Rogerbot / SiteAuditBot / Telegrambot / Twitterbot / UptimeRobot
|
||||
// Google Site Verifier / Meta / Yahoo! Japan
|
||||
// Iframely - https://iframely.com/docs/about
|
||||
// Perplexity-User - https://docs.perplexity.ai/guides/bots
|
||||
// MistralAI-User - https://docs.mistral.ai/robots/
|
||||
// Yandex Bots - https://yandex.com/bots
|
||||
/(ahrefssiteaudit|(?:bing|microsoft)preview|(?:chatgpt|mistralai|perplexity)-user|mastodon|(?:discord|duckassist|linkedin|pinterest|reddit|roger|siteaudit|twitter|uptimero)bot|google-site-verification|iframely|meta-externalfetcher|y!?j-dlc|yandex(?:calendar|direct(?:dyn)?|searchshop)|yadirectfetcher)\/([\w\.]+)/i,
|
||||
/(asana|ahrefssiteaudit|(?:bing|microsoft)preview|blueno|(?:chatgpt|claude|mistralai|perplexity)-user|cohere-ai|hubspot page fetcher|mastodon|(?:bitly|bufferlinkpreview|discord|duckassist|linkedin|pinterest|reddit|roger|siteaudit|twitter|uptimero|zoom)bot|google-site-verification|iframely|kakaotalk-scrap|meta-externalfetcher|y!?j-dlc|yandex(?:calendar|direct(?:dyn)?|fordomain|pagechecker|searchshop)|yadirectfetcher)\/([\w\.]+)/i,
|
||||
|
||||
// Bluesky
|
||||
/(bluesky) cardyb\/([\w\.]+)/i,
|
||||
@@ -260,8 +285,8 @@ const Fetchers = Object.freeze({
|
||||
[NAME, VERSION, [TYPE, FETCHER]],
|
||||
|
||||
[
|
||||
// Google Bots / Cohere / Snapchat / Vercelbot / Yandex Bots
|
||||
/((?:better uptime |telegram|vercel)bot|cohere-ai|feedfetcher-google|google(?:imageproxy|-read-aloud|-pagerenderer|producer)|snap url preview|yandex(?:sitelinks|userproxy))/i
|
||||
// Google Bots / Chrome-Lighthouse / Gemini-Deep-Research / KeybaseBot / Snapchat / Vercelbot / Yandex Bots
|
||||
/((?:better uptime |keybase|telegram|vercel)bot|chrome-lighthouse|feedfetcher-google|gemini-deep-research|google(?:imageproxy|-read-aloud|-pagerenderer|producer)|snap url preview|vercel(flags|tracing|-(favicon|screenshot)-bot)|yandex(?:sitelinks|userproxy))/i
|
||||
],
|
||||
[NAME, [TYPE, FETCHER]],
|
||||
],
|
||||
@@ -404,8 +429,8 @@ const Vehicles = Object.freeze({
|
||||
const Bots = Object.freeze({
|
||||
browser : [
|
||||
...CLIs.browser,
|
||||
...Crawlers.browser,
|
||||
...Fetchers.browser,
|
||||
...Crawlers.browser,
|
||||
...Libraries.browser
|
||||
],
|
||||
os : [
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// Source: /src/extensions/ua-parser-extensions.js
|
||||
|
||||
///////////////////////////////////////////////
|
||||
/* Extensions for UAParser.js v2.0.4
|
||||
/* Extensions for UAParser.js v2.0.6
|
||||
https://github.com/faisalman/ua-parser-js
|
||||
Author: Faisal Salman <f@faisalman.com>
|
||||
UAParser.js PRO Personal License */
|
||||
@@ -47,20 +47,33 @@ const Crawlers = Object.freeze({
|
||||
// AhrefsBot - https://ahrefs.com/robot
|
||||
// Amazonbot - https://developer.amazon.com/amazonbot
|
||||
// Bingbot / AdIdxBot - https://www.bing.com/webmasters/help/which-crawlers-does-bing-use-8c184ec0
|
||||
// Bravebot - https://search.brave.com/help/brave-search-crawler
|
||||
// CCBot - https://commoncrawl.org/faq
|
||||
// contxbot - https://affiliate-program.amazon.com/help/node/topic/GT98G5PPRERNVZ2C
|
||||
// Coveobot - https://connect.coveo.com/s/article/19648
|
||||
// CriteoBot - https://www.criteo.com/criteo-crawler/
|
||||
// Dotbot - https://moz.com/help/moz-procedures/crawlers/dotbot
|
||||
// DuckDuckBot - http://duckduckgo.com/duckduckbot.html
|
||||
// FacebookBot - https://developers.facebook.com/docs/sharing/bot/
|
||||
// GPTBot - https://platform.openai.com/docs/gptbot
|
||||
// iAskBot - https://iask.ai
|
||||
// Kagibot - https://kagi.com/bot
|
||||
// Kangaroo Bot - https://kangaroollm.com.au/kangaroo-bot/
|
||||
// LinkedInBot - http://www.linkedin.com
|
||||
// MJ12bot - https://mj12bot.com/
|
||||
// MojeekBot - https://www.mojeek.com/bot.html
|
||||
// Onespot - https://www.onespot.com/identifying-traffic.html
|
||||
// OpenAI's SearchGPT - https://platform.openai.com/docs/bots
|
||||
// PerplexityBot - https://perplexity.ai/perplexitybot
|
||||
// SBIntuitionsBot - https://www.sbintuitions.co.jp/bot/
|
||||
// SeznamBot - http://napoveda.seznam.cz/seznambot-intro
|
||||
/((?:adidx|ahrefs|amazon|bing|cc|dot|duckduck|exa|facebook|gpt|iask|linkedin|mj12|mojeek|oai-search|onespot-scraper|perplexity|semrush|seznam)bot)\/([\w\.-]+)/i,
|
||||
// SurdotlyBot - http://sur.ly/bot.html
|
||||
// Swiftbot - https://swiftype.com/swiftbot
|
||||
// YepBot - https://yep.com/yepbot/
|
||||
/((?:adidx|ahrefs|amazon|bing|brave|cc|contx|coveo|criteo|dot|duckduck(?:go-favicons-)?|exa|facebook|gpt|iask|kagi|kangaroo |linkedin|mj12|mojeek|oai-search|onespot-scraper|perplexity|sbintuitions|semrush|seznam|surdotly|swift|yep)bot)\/([\w\.-]+)/i,
|
||||
|
||||
// Algolia Crawler
|
||||
/(algolia crawler(?: renderscript)?)\/?([\w\.]*)/i,
|
||||
|
||||
// Applebot - http://apple.com/go/applebot
|
||||
/(applebot(?:-extended)?)\/?([\w\.]*)/i,
|
||||
@@ -69,7 +82,7 @@ const Crawlers = Object.freeze({
|
||||
/(baiduspider[-imagevdonwsfcpr]{0,7})\/?([\w\.]*)/i,
|
||||
|
||||
// ClaudeBot (Anthropic)
|
||||
/(claude(?:bot|-web)|anthropic-ai)\/?([\w\.]*)/i,
|
||||
/(claude(?:bot|-searchbot|-web)|anthropic-ai)\/?([\w\.]*)/i,
|
||||
|
||||
// Coc Coc Bot - https://help.coccoc.com/en/search-engine
|
||||
/(coccocbot-(?:image|web))\/([\w\.]+)/i,
|
||||
@@ -87,8 +100,11 @@ const Crawlers = Object.freeze({
|
||||
// Internet Archive (archive.org)
|
||||
/(ia_archiver|archive\.org_bot)\/?([\w\.]*)/i,
|
||||
|
||||
// OnCrawl
|
||||
/(oncrawl) mobile\/([\w\.]+)/i,
|
||||
|
||||
// Qwantbot - https://help.qwant.com/bot
|
||||
/(qwantbot)[-\w]*\/?([\w\.]*)/i,
|
||||
/(qwantbot(?:-news)?)[-\w]*\/?([\w\.]*)/i,
|
||||
|
||||
// SemrushBot - http://www.semrush.com/bot.html
|
||||
/((?:semrush|splitsignal)bot[-abcfimostw]*)\/?([\w\.-]*)/i,
|
||||
@@ -100,30 +116,38 @@ const Crawlers = Object.freeze({
|
||||
/(y!?j-(?:asr|br[uw]|dscv|mmp|vsidx|wsc))\/([\w\.]+)/i,
|
||||
|
||||
// Yandex Bots - https://yandex.com/bots
|
||||
/(yandex(?:(?:mobile)?(?:accessibility|additional|renderresources|screenshot|sprav)?bot|image(?:s|resizer)|video(?:parser)?|blogs|adnet|favicons|fordomain|market|media|metrika|news|ontodb(?:api)?|pagechecker|partner|rca|tracker|turbo|vertis|webmaster|antivirus))\/([\w\.]+)/i,
|
||||
/(yandex(?:(?:mobile)?(?:accessibility|additional|com|renderresources|screenshot|sprav)?bot(?!.+mirror)|image(?:s|resizer)|adnet|blogs|favicons|market|media|metrika|news|ontodb(?:api)?|partner|rca|tracker|turbo|verti(?:cal)?s|webmaster|video(?:parser)?))\/([\w\.]+)/i,
|
||||
|
||||
// Yeti (Naver)
|
||||
/(yeti)\/([\w\.]+)/i,
|
||||
|
||||
// aiHitBot / Diffbot / Linespider / Magpie-Crawler / Omgilibot / OpenAI Image Downloader / Webzio-Extended / Screaming Frog SEO Spider / Startpage / Timpibot / VelenPublicWebCrawler / YisouSpider / YouBot
|
||||
/((?:aihit|diff|timpi|you)bot|omgili(?:bot)?|openai image downloader|(?:magpie-|velenpublicweb)crawler|startpageprivateimageproxy|webzio-extended|(?:chatglm-|line|screaming frog seo |yisou)spider)\/?([\w\.]*)/i
|
||||
// aiHitBot / Algolia Crawler / BLEXBot / Diffbot / FirecrawlAgent / HuggingFace-Bot / Linespider / MSNBot / Magpie-Crawler / Omgilibot / OpenAI Image Downloader / PanguBot / Replicate-Bot / RunPod-Bot / Webzio-Extended / Screaming Frog SEO Spider / Startpage / Timpibot / Together-Bot / VelenPublicWebCrawler / xAI-Bot / YisouSpider / YouBot / ZumBot
|
||||
// Cotoyogi - https://ds.rois.ac.jp/en_center8/en_crawler/
|
||||
// Freespoke - https://docs.freespoke.com/search/bot/
|
||||
/((?:aihit|blex|diff|huggingface-|msn|pangu|replicate-|runpod-|timpi|together-|xai-|you|zum)bot|(?:magpie-|velenpublicweb)crawler|(?:chatglm-|line|screaming frog seo |yisou)spider|cotoyogi|firecrawlagent|freespoke|omgili(?:bot)?|openai image downloader|startpageprivateimageproxy|twinagent|webzio-extended)\/?([\w\.]*)/i
|
||||
],
|
||||
|
||||
[NAME, VERSION, [TYPE, CRAWLER]],
|
||||
|
||||
[
|
||||
// YandexBot MirrorDetector
|
||||
/(yandexbot\/([\w\.]+); mirrordetector)/i
|
||||
],
|
||||
[[NAME, /\/.+;/ig, ''], VERSION, [TYPE, CRAWLER]],
|
||||
|
||||
[
|
||||
// Google Bots
|
||||
/((?:adsbot|apis|mediapartners)-google(?:-mobile)?|google-?(?:other|cloudvertexbot|extended|safety))/i,
|
||||
|
||||
// AI2Bot - https://allenai.org/crawler
|
||||
// Bytespider
|
||||
// DataForSeoBot - https://dataforseo.com/dataforseo-bot
|
||||
// Huawei AspiegelBot / PetalBot https://aspiegel.com/petalbot
|
||||
// ImagesiftBot - https://imagesift.com/about
|
||||
// Qihoo 360Spider
|
||||
// Siteimprove - https://help.siteimprove.com/support/solutions/articles/80000448553
|
||||
// TurnitinBot - https://www.turnitin.com/robot/crawlerinfo.html
|
||||
// v0bot - https://vercel.com/docs/bot-management
|
||||
// Yahoo! Slurp - http://help.yahoo.com/help/us/ysearch/slurp
|
||||
/\b(360spider-?(?:image|video)?|bytespider|(?:ai2|aspiegel|dataforseo|imagesift|petal|turnitin)bot|teoma|yahoo! slurp)/i
|
||||
// Botify / Bytespider / DeepSeekBot / Qihoo 360Spider / SeekportBot / TikTokSpider
|
||||
/\b((ai2|aspiegel|dataforseo|deepseek|imagesift|petal|seekport|turnitin|v0)bot|360spider-?(image|video)?|baidu-ads|botify|(byte|tiktok)spider|cohere-training-data-crawler|elastic(?=\/s)|marginalia|siteimprove(?=bot|\.com)|teoma|webzio|yahoo! slurp)/i
|
||||
],
|
||||
[NAME, [TYPE, CRAWLER]]
|
||||
]
|
||||
@@ -238,16 +262,17 @@ const Emails = Object.freeze({
|
||||
const Fetchers = Object.freeze({
|
||||
browser : [
|
||||
[
|
||||
// Asana / Bitlybot / Better Uptime / BingPreview / Blueno / Cohere-AI / HubSpot Page Fetcher / kakaotalk-scrap / Mastodon / MicrosoftPreview / Pinterestbot / Redditbot / Rogerbot / SiteAuditBot / Telegrambot / Twitterbot / UptimeRobot
|
||||
// AhrefsSiteAudit - https://ahrefs.com/robot/site-audit
|
||||
// Buffer Link Preview Bot - https://scraper.buffer.com/about/bots/link-preview-bot
|
||||
// ChatGPT-User - https://platform.openai.com/docs/plugins/bot
|
||||
// DuckAssistBot - https://duckduckgo.com/duckassistbot/
|
||||
// Better Uptime / BingPreview / Mastodon / MicrosoftPreview / Pinterestbot / Redditbot / Rogerbot / SiteAuditBot / Telegrambot / Twitterbot / UptimeRobot
|
||||
// Google Site Verifier / Meta / Yahoo! Japan
|
||||
// Iframely - https://iframely.com/docs/about
|
||||
// Perplexity-User - https://docs.perplexity.ai/guides/bots
|
||||
// MistralAI-User - https://docs.mistral.ai/robots/
|
||||
// Yandex Bots - https://yandex.com/bots
|
||||
/(ahrefssiteaudit|(?:bing|microsoft)preview|(?:chatgpt|mistralai|perplexity)-user|mastodon|(?:discord|duckassist|linkedin|pinterest|reddit|roger|siteaudit|twitter|uptimero)bot|google-site-verification|iframely|meta-externalfetcher|y!?j-dlc|yandex(?:calendar|direct(?:dyn)?|searchshop)|yadirectfetcher)\/([\w\.]+)/i,
|
||||
/(asana|ahrefssiteaudit|(?:bing|microsoft)preview|blueno|(?:chatgpt|claude|mistralai|perplexity)-user|cohere-ai|hubspot page fetcher|mastodon|(?:bitly|bufferlinkpreview|discord|duckassist|linkedin|pinterest|reddit|roger|siteaudit|twitter|uptimero|zoom)bot|google-site-verification|iframely|kakaotalk-scrap|meta-externalfetcher|y!?j-dlc|yandex(?:calendar|direct(?:dyn)?|fordomain|pagechecker|searchshop)|yadirectfetcher)\/([\w\.]+)/i,
|
||||
|
||||
// Bluesky
|
||||
/(bluesky) cardyb\/([\w\.]+)/i,
|
||||
@@ -264,8 +289,8 @@ const Fetchers = Object.freeze({
|
||||
[NAME, VERSION, [TYPE, FETCHER]],
|
||||
|
||||
[
|
||||
// Google Bots / Cohere / Snapchat / Vercelbot / Yandex Bots
|
||||
/((?:better uptime |telegram|vercel)bot|cohere-ai|feedfetcher-google|google(?:imageproxy|-read-aloud|-pagerenderer|producer)|snap url preview|yandex(?:sitelinks|userproxy))/i
|
||||
// Google Bots / Chrome-Lighthouse / Gemini-Deep-Research / KeybaseBot / Snapchat / Vercelbot / Yandex Bots
|
||||
/((?:better uptime |keybase|telegram|vercel)bot|chrome-lighthouse|feedfetcher-google|gemini-deep-research|google(?:imageproxy|-read-aloud|-pagerenderer|producer)|snap url preview|vercel(flags|tracing|-(favicon|screenshot)-bot)|yandex(?:sitelinks|userproxy))/i
|
||||
],
|
||||
[NAME, [TYPE, FETCHER]],
|
||||
],
|
||||
@@ -408,8 +433,8 @@ const Vehicles = Object.freeze({
|
||||
const Bots = Object.freeze({
|
||||
browser : [
|
||||
...CLIs.browser,
|
||||
...Crawlers.browser,
|
||||
...Fetchers.browser,
|
||||
...Crawlers.browser,
|
||||
...Libraries.browser
|
||||
],
|
||||
os : [
|
||||
|
||||
32
src/helpers/ua-parser-helpers.d.ts
vendored
32
src/helpers/ua-parser-helpers.d.ts
vendored
@@ -1,27 +1,15 @@
|
||||
// Type definitions for Helpers submodule of UAParser.js v2.0.4
|
||||
// Type definitions for Helpers submodule of UAParser.js v2.0.5
|
||||
// Project: https://github.com/faisalman/ua-parser-js
|
||||
// Definitions by: Faisal Salman <https://github.com/faisalman>
|
||||
|
||||
import type { IResult } from "../main/ua-parser";
|
||||
|
||||
declare function getDeviceVendor(model: string): string | undefined;
|
||||
declare function isAppleSilicon(resultOrUA: IResult | string): boolean;
|
||||
declare function isAIBot(resultOrUA: IResult | string): boolean;
|
||||
declare function isBot(resultOrUA: IResult | string): boolean;
|
||||
declare function isChromeFamily(resultOrUA: IResult | string): boolean;
|
||||
declare function isElectron(): boolean;
|
||||
declare function isFromEU(): boolean;
|
||||
declare function isFrozenUA(ua: string): boolean;
|
||||
declare function isStandalonePWA(): boolean;
|
||||
|
||||
export {
|
||||
getDeviceVendor,
|
||||
isAppleSilicon,
|
||||
isAIBot,
|
||||
isBot,
|
||||
isChromeFamily,
|
||||
isElectron,
|
||||
isFromEU,
|
||||
isFrozenUA,
|
||||
isStandalonePWA
|
||||
}
|
||||
export function getDeviceVendor(model: string): string | undefined;
|
||||
export function isAppleSilicon(resultOrUA: IResult | string): boolean;
|
||||
export function isAIBot(resultOrUA: IResult | string): boolean;
|
||||
export function isBot(resultOrUA: IResult | string): boolean;
|
||||
export function isChromeFamily(resultOrUA: IResult | string): boolean;
|
||||
export function isElectron(): boolean;
|
||||
export function isFromEU(): boolean;
|
||||
export function isFrozenUA(ua: string): boolean;
|
||||
export function isStandalonePWA(): boolean;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////
|
||||
/* Helpers for UAParser.js v2.0.4
|
||||
/* Helpers for UAParser.js v2.0.6
|
||||
https://github.com/faisalman/ua-parser-js
|
||||
Author: Faisal Salman <f@faisalman.com>
|
||||
UAParser.js PRO Personal License */
|
||||
@@ -8,11 +8,12 @@
|
||||
/*jshint esversion: 6 */
|
||||
|
||||
const { UAParser } = require('../main/ua-parser');
|
||||
const { CPU, OS, Engine } = require('../enums/ua-parser-enums');
|
||||
const { Bots } = require('../extensions/ua-parser-extensions');
|
||||
const { CPUArch, OSName, EngineName, Extension, BrowserType } = require('../enums/ua-parser-enums');
|
||||
const { Bots, Crawlers } = require('../extensions/ua-parser-extensions');
|
||||
const { isFromEU } = require('detect-europe-js');
|
||||
const { isFrozenUA } = require('ua-is-frozen');
|
||||
const { isStandalonePWA } = require('is-standalone-pwa');
|
||||
const { Crawler } = Extension.BrowserName;
|
||||
|
||||
const toResult = (value, head, ext) => typeof value === 'string' ? UAParser(value, head, ext) : value;
|
||||
|
||||
@@ -20,8 +21,8 @@ const getDeviceVendor = (model) => UAParser(`Mozilla/5.0 (Linux; Android 10; ${m
|
||||
|
||||
const isAppleSilicon = (resultOrUA) => {
|
||||
const res = toResult(resultOrUA);
|
||||
if (res.os.is(OS.MACOS)) {
|
||||
if (res.cpu.is(CPU.ARM)) {
|
||||
if (res.os.is(OSName.MACOS)) {
|
||||
if (res.cpu.is(CPUArch.ARM)) {
|
||||
return true;
|
||||
}
|
||||
if (typeof resultOrUA !== 'string' && typeof window !== 'undefined') {
|
||||
@@ -44,88 +45,129 @@ const isAppleSilicon = (resultOrUA) => {
|
||||
const isAIBot = (resultOrUA) => [
|
||||
|
||||
// AI2
|
||||
'ai2bot',
|
||||
Crawler.AI2_BOT,
|
||||
|
||||
// Amazon
|
||||
'amazonbot',
|
||||
Crawler.AMAZON_BOT,
|
||||
|
||||
// Anthropic
|
||||
'anthropic-ai',
|
||||
'claude-web',
|
||||
'claudebot',
|
||||
Crawler.ANTHROPIC_AI,
|
||||
Crawler.ANTHROPIC_CLAUDE_BOT,
|
||||
Crawler.ANTHROPIC_CLAUDE_SEARCHBOT,
|
||||
Crawler.ANTHROPIC_CLAUDE_WEB,
|
||||
|
||||
// Apple
|
||||
'applebot',
|
||||
'applebot-extended',
|
||||
Crawler.APPLE_BOT,
|
||||
Crawler.APPLE_BOT_EXTENDED,
|
||||
|
||||
// Brave
|
||||
Crawler.BRAVE_BOT,
|
||||
|
||||
// ByteDance
|
||||
'bytespider',
|
||||
Crawler.BYTEDANCE_BYTESPIDER,
|
||||
Crawler.BYTEDANCE_TIKTOKSPIDER,
|
||||
|
||||
// Cohere
|
||||
Crawler.COHERE_TRAINING_DATA_CRAWLER,
|
||||
|
||||
// Common Crawl
|
||||
'ccbot',
|
||||
Crawler.COMMON_CRAWL_CCBOT,
|
||||
|
||||
// Coveo
|
||||
Crawler.COVEO_BOT,
|
||||
|
||||
// DataForSeo
|
||||
'dataforseobot',
|
||||
Crawler.DATAFORSEO_BOT,
|
||||
|
||||
// DeepSeek
|
||||
Crawler.DEEPSEEK_BOT,
|
||||
|
||||
// Diffbot
|
||||
'diffbot',
|
||||
Crawler.DIFFBOT,
|
||||
|
||||
// Google
|
||||
'googleother',
|
||||
'googleother-image',
|
||||
'googleother-video',
|
||||
'google-extended',
|
||||
Crawler.GOOGLE_EXTENDED,
|
||||
Crawler.GOOGLE_OTHER,
|
||||
Crawler.GOOGLE_OTHER_IMAGE,
|
||||
Crawler.GOOGLE_OTHER_VIDEO,
|
||||
Crawler.GOOGLE_CLOUDVERTEXBOT,
|
||||
|
||||
// Hive AI
|
||||
'imagesiftbot',
|
||||
Crawler.HIVE_IMAGESIFTBOT,
|
||||
|
||||
// Huawei
|
||||
'petalbot',
|
||||
Crawler.HUAWEI_PETALBOT,
|
||||
Crawler.HUAWEI_PANGUBOT,
|
||||
|
||||
// Hugging Face
|
||||
Crawler.HUGGINGFACE_BOT,
|
||||
|
||||
// Kangaroo
|
||||
Crawler.KANGAROO_BOT,
|
||||
|
||||
// Mendable.ai
|
||||
Crawler.FIRECRAWL_AGENT,
|
||||
|
||||
// Meta
|
||||
'facebookbot',
|
||||
'meta-externalagent',
|
||||
Crawler.META_FACEBOOKBOT,
|
||||
Crawler.META_EXTERNALAGENT,
|
||||
|
||||
// OpenAI
|
||||
'gptbot',
|
||||
'oai-searchbot',
|
||||
Crawler.OPENAI_GPTBOT,
|
||||
Crawler.OPENAI_SEARCH_BOT,
|
||||
|
||||
// Perplexity
|
||||
'perplexitybot',
|
||||
Crawler.PERPLEXITY_BOT,
|
||||
|
||||
// Replicate
|
||||
Crawler.REPLICATE_BOT,
|
||||
|
||||
// Runpod
|
||||
Crawler.RUNPOD_BOT,
|
||||
|
||||
// SB Intuitions
|
||||
Crawler.SB_INTUITIONS_BOT,
|
||||
|
||||
// Semrush
|
||||
'semrushbot-ocob',
|
||||
Crawler.SEMRUSH_BOT_CONTENTSHAKE,
|
||||
|
||||
// Timpi
|
||||
'timpibot',
|
||||
Crawler.TIMPI_BOT,
|
||||
|
||||
// Together AI
|
||||
Crawler.TOGETHER_BOT,
|
||||
|
||||
// Velen.io
|
||||
'velenpublicwebcrawler',
|
||||
Crawler.HUNTER_VELENPUBLICWEBCRAWLER,
|
||||
|
||||
// Vercel
|
||||
Crawler.VERCEL_V0BOT,
|
||||
|
||||
// Webz.io
|
||||
'omgili',
|
||||
'omgilibot',
|
||||
'webzio-extended',
|
||||
Crawler.WEBZIO_OMGILI,
|
||||
Crawler.WEBZIO_OMGILI_BOT,
|
||||
Crawler.WEBZIO_EXTENDED,
|
||||
|
||||
// X
|
||||
Crawler.XAI_BOT,
|
||||
|
||||
// You.com
|
||||
'youbot',
|
||||
Crawler.YOU_BOT,
|
||||
|
||||
// Zhipu AI
|
||||
'chatglm-spider',
|
||||
|
||||
// Zyte
|
||||
'scrapy'
|
||||
|
||||
].includes(String(toResult(resultOrUA, Bots).browser.name).toLowerCase());
|
||||
Crawler.ZHIPU_CHATGLM_SPIDER
|
||||
]
|
||||
.map((s) => s.toLowerCase())
|
||||
.includes(String(toResult(resultOrUA, Crawlers).browser.name).toLowerCase());
|
||||
|
||||
const isBot = (resultOrUA) => [
|
||||
'cli',
|
||||
'crawler',
|
||||
'fetcher',
|
||||
'library'
|
||||
BrowserType.CLI,
|
||||
BrowserType.CRAWLER,
|
||||
BrowserType.FETCHER,
|
||||
BrowserType.LIBRARY
|
||||
].includes(toResult(resultOrUA, Bots).browser.type);
|
||||
|
||||
const isChromeFamily = (resultOrUA) => toResult(resultOrUA).engine.is(Engine.BLINK);
|
||||
const isChromeFamily = (resultOrUA) => toResult(resultOrUA).engine.is(EngineName.BLINK);
|
||||
|
||||
const isElectron = () => !!(process?.versions?.hasOwnProperty('electron') || // node.js
|
||||
/ electron\//i.test(navigator?.userAgent)); // browser
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// Source: /src/helpers/ua-parser-helpers.js
|
||||
|
||||
///////////////////////////////////////////////
|
||||
/* Helpers for UAParser.js v2.0.4
|
||||
/* Helpers for UAParser.js v2.0.6
|
||||
https://github.com/faisalman/ua-parser-js
|
||||
Author: Faisal Salman <f@faisalman.com>
|
||||
UAParser.js PRO Personal License */
|
||||
@@ -12,11 +12,12 @@
|
||||
/*jshint esversion: 6 */
|
||||
|
||||
import { UAParser } from '../main/ua-parser.mjs';
|
||||
import { CPU, OS, Engine } from '../enums/ua-parser-enums.mjs';
|
||||
import { Bots } from '../extensions/ua-parser-extensions.mjs';
|
||||
import { CPUArch, OSName, EngineName, Extension, BrowserType } from '../enums/ua-parser-enums.mjs';
|
||||
import { Bots, Crawlers } from '../extensions/ua-parser-extensions.mjs';
|
||||
import { isFromEU } from 'detect-europe-js';
|
||||
import { isFrozenUA } from 'ua-is-frozen';
|
||||
import { isStandalonePWA } from 'is-standalone-pwa';
|
||||
const { Crawler } = Extension.BrowserName;
|
||||
|
||||
const toResult = (value, head, ext) => typeof value === 'string' ? UAParser(value, head, ext) : value;
|
||||
|
||||
@@ -24,8 +25,8 @@ const getDeviceVendor = (model) => UAParser(`Mozilla/5.0 (Linux; Android 10; ${m
|
||||
|
||||
const isAppleSilicon = (resultOrUA) => {
|
||||
const res = toResult(resultOrUA);
|
||||
if (res.os.is(OS.MACOS)) {
|
||||
if (res.cpu.is(CPU.ARM)) {
|
||||
if (res.os.is(OSName.MACOS)) {
|
||||
if (res.cpu.is(CPUArch.ARM)) {
|
||||
return true;
|
||||
}
|
||||
if (typeof resultOrUA !== 'string' && typeof window !== 'undefined') {
|
||||
@@ -48,88 +49,129 @@ const isAppleSilicon = (resultOrUA) => {
|
||||
const isAIBot = (resultOrUA) => [
|
||||
|
||||
// AI2
|
||||
'ai2bot',
|
||||
Crawler.AI2_BOT,
|
||||
|
||||
// Amazon
|
||||
'amazonbot',
|
||||
Crawler.AMAZON_BOT,
|
||||
|
||||
// Anthropic
|
||||
'anthropic-ai',
|
||||
'claude-web',
|
||||
'claudebot',
|
||||
Crawler.ANTHROPIC_AI,
|
||||
Crawler.ANTHROPIC_CLAUDE_BOT,
|
||||
Crawler.ANTHROPIC_CLAUDE_SEARCHBOT,
|
||||
Crawler.ANTHROPIC_CLAUDE_WEB,
|
||||
|
||||
// Apple
|
||||
'applebot',
|
||||
'applebot-extended',
|
||||
Crawler.APPLE_BOT,
|
||||
Crawler.APPLE_BOT_EXTENDED,
|
||||
|
||||
// Brave
|
||||
Crawler.BRAVE_BOT,
|
||||
|
||||
// ByteDance
|
||||
'bytespider',
|
||||
Crawler.BYTEDANCE_BYTESPIDER,
|
||||
Crawler.BYTEDANCE_TIKTOKSPIDER,
|
||||
|
||||
// Cohere
|
||||
Crawler.COHERE_TRAINING_DATA_CRAWLER,
|
||||
|
||||
// Common Crawl
|
||||
'ccbot',
|
||||
Crawler.COMMON_CRAWL_CCBOT,
|
||||
|
||||
// Coveo
|
||||
Crawler.COVEO_BOT,
|
||||
|
||||
// DataForSeo
|
||||
'dataforseobot',
|
||||
Crawler.DATAFORSEO_BOT,
|
||||
|
||||
// DeepSeek
|
||||
Crawler.DEEPSEEK_BOT,
|
||||
|
||||
// Diffbot
|
||||
'diffbot',
|
||||
Crawler.DIFFBOT,
|
||||
|
||||
// Google
|
||||
'googleother',
|
||||
'googleother-image',
|
||||
'googleother-video',
|
||||
'google-extended',
|
||||
Crawler.GOOGLE_EXTENDED,
|
||||
Crawler.GOOGLE_OTHER,
|
||||
Crawler.GOOGLE_OTHER_IMAGE,
|
||||
Crawler.GOOGLE_OTHER_VIDEO,
|
||||
Crawler.GOOGLE_CLOUDVERTEXBOT,
|
||||
|
||||
// Hive AI
|
||||
'imagesiftbot',
|
||||
Crawler.HIVE_IMAGESIFTBOT,
|
||||
|
||||
// Huawei
|
||||
'petalbot',
|
||||
Crawler.HUAWEI_PETALBOT,
|
||||
Crawler.HUAWEI_PANGUBOT,
|
||||
|
||||
// Hugging Face
|
||||
Crawler.HUGGINGFACE_BOT,
|
||||
|
||||
// Kangaroo
|
||||
Crawler.KANGAROO_BOT,
|
||||
|
||||
// Mendable.ai
|
||||
Crawler.FIRECRAWL_AGENT,
|
||||
|
||||
// Meta
|
||||
'facebookbot',
|
||||
'meta-externalagent',
|
||||
Crawler.META_FACEBOOKBOT,
|
||||
Crawler.META_EXTERNALAGENT,
|
||||
|
||||
// OpenAI
|
||||
'gptbot',
|
||||
'oai-searchbot',
|
||||
Crawler.OPENAI_GPTBOT,
|
||||
Crawler.OPENAI_SEARCH_BOT,
|
||||
|
||||
// Perplexity
|
||||
'perplexitybot',
|
||||
Crawler.PERPLEXITY_BOT,
|
||||
|
||||
// Replicate
|
||||
Crawler.REPLICATE_BOT,
|
||||
|
||||
// Runpod
|
||||
Crawler.RUNPOD_BOT,
|
||||
|
||||
// SB Intuitions
|
||||
Crawler.SB_INTUITIONS_BOT,
|
||||
|
||||
// Semrush
|
||||
'semrushbot-ocob',
|
||||
Crawler.SEMRUSH_BOT_CONTENTSHAKE,
|
||||
|
||||
// Timpi
|
||||
'timpibot',
|
||||
Crawler.TIMPI_BOT,
|
||||
|
||||
// Together AI
|
||||
Crawler.TOGETHER_BOT,
|
||||
|
||||
// Velen.io
|
||||
'velenpublicwebcrawler',
|
||||
Crawler.HUNTER_VELENPUBLICWEBCRAWLER,
|
||||
|
||||
// Vercel
|
||||
Crawler.VERCEL_V0BOT,
|
||||
|
||||
// Webz.io
|
||||
'omgili',
|
||||
'omgilibot',
|
||||
'webzio-extended',
|
||||
Crawler.WEBZIO_OMGILI,
|
||||
Crawler.WEBZIO_OMGILI_BOT,
|
||||
Crawler.WEBZIO_EXTENDED,
|
||||
|
||||
// X
|
||||
Crawler.XAI_BOT,
|
||||
|
||||
// You.com
|
||||
'youbot',
|
||||
Crawler.YOU_BOT,
|
||||
|
||||
// Zhipu AI
|
||||
'chatglm-spider',
|
||||
|
||||
// Zyte
|
||||
'scrapy'
|
||||
|
||||
].includes(String(toResult(resultOrUA, Bots).browser.name).toLowerCase());
|
||||
Crawler.ZHIPU_CHATGLM_SPIDER
|
||||
]
|
||||
.map((s) => s.toLowerCase())
|
||||
.includes(String(toResult(resultOrUA, Crawlers).browser.name).toLowerCase());
|
||||
|
||||
const isBot = (resultOrUA) => [
|
||||
'cli',
|
||||
'crawler',
|
||||
'fetcher',
|
||||
'library'
|
||||
BrowserType.CLI,
|
||||
BrowserType.CRAWLER,
|
||||
BrowserType.FETCHER,
|
||||
BrowserType.LIBRARY
|
||||
].includes(toResult(resultOrUA, Bots).browser.type);
|
||||
|
||||
const isChromeFamily = (resultOrUA) => toResult(resultOrUA).engine.is(Engine.BLINK);
|
||||
const isChromeFamily = (resultOrUA) => toResult(resultOrUA).engine.is(EngineName.BLINK);
|
||||
|
||||
const isElectron = () => !!(process?.versions?.hasOwnProperty('electron') || // node.js
|
||||
/ electron\//i.test(navigator?.userAgent)); // browser
|
||||
|
||||
15
src/main/ua-parser.d.ts
vendored
15
src/main/ua-parser.d.ts
vendored
@@ -1,9 +1,8 @@
|
||||
// Type definitions for UAParser.js v2.0.4
|
||||
// Type definitions for UAParser.js v2.0.6
|
||||
// Project: https://github.com/faisalman/ua-parser-js
|
||||
// Definitions by: Faisal Salman <https://github.com/faisalman>
|
||||
|
||||
import type { IncomingHttpHeaders } from 'http';
|
||||
import type { Headers as FetchAPIHeaders } from 'node-fetch';
|
||||
import { BrowserType, CPUArch, DeviceType, EngineName } from "../enums/ua-parser-enums";
|
||||
|
||||
declare namespace UAParser {
|
||||
|
||||
@@ -18,21 +17,21 @@ declare namespace UAParser {
|
||||
name?: string;
|
||||
version?: string;
|
||||
major?: string;
|
||||
type?: 'crawler' | 'cli' | 'email' | 'fetcher' | 'inapp' | 'mediaplayer' | 'library';
|
||||
type?: typeof BrowserType[keyof typeof BrowserType];
|
||||
}
|
||||
|
||||
interface ICPU extends IData<ICPU> {
|
||||
architecture?: 'ia32' | 'ia64' | 'amd64' | 'arm' | 'arm64' | 'armhf' | 'avr' | 'avr32' | 'irix' | 'irix64' | 'mips' | 'mips64' | '68k' | 'pa-risc' | 'ppc' | 'sparc' | 'sparc64';
|
||||
architecture?: typeof CPUArch[keyof typeof CPUArch];
|
||||
}
|
||||
|
||||
interface IDevice extends IData<IDevice> {
|
||||
type?: 'mobile' | 'tablet' | 'console' | 'smarttv' | 'wearable' | 'xr' | 'embedded';
|
||||
type?: typeof DeviceType[keyof typeof DeviceType];
|
||||
vendor?: string;
|
||||
model?: string;
|
||||
}
|
||||
|
||||
interface IEngine extends IData<IEngine> {
|
||||
name?: 'Amaya' | 'ArkWeb' | 'Blink' | 'EdgeHTML' | 'Flow' | 'Gecko' | 'Goanna' | 'iCab' | 'KHTML' | 'LibWeb' | 'Links' | 'Lynx' | 'NetFront' | 'NetSurf' | 'Presto' | 'Servo' | 'Tasman' | 'Trident' | 'w3m' | 'WebKit';
|
||||
name?: typeof EngineName[keyof typeof EngineName];
|
||||
version?: string;
|
||||
}
|
||||
|
||||
@@ -53,7 +52,7 @@ declare namespace UAParser {
|
||||
type RegexMap = ((RegExp | string | (string | RegExp | Function)[])[])[];
|
||||
type UAParserProps = 'browser' | 'cpu' | 'device' | 'engine' | 'os';
|
||||
type UAParserExt = Partial<Record<UAParserProps, RegexMap>> | Partial<Record<UAParserProps, RegexMap>>[];
|
||||
type UAParserHeaders = Record<string, string> | IncomingHttpHeaders | FetchAPIHeaders;
|
||||
export type UAParserHeaders = Record<string, string | string[] | undefined> | Headers;
|
||||
|
||||
export function UAParser(uastring?: string, extensions?: UAParserExt, headers?: UAParserHeaders): IResult;
|
||||
export function UAParser(uastring?: string, headers?: UAParserHeaders): IResult;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/* UAParser.js v2.0.4
|
||||
/* UAParser.js v2.0.6
|
||||
Copyright © 2012-2025 Faisal Salman <f@faisalman.com>
|
||||
UAParser.js PRO Personal License *//*
|
||||
Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.
|
||||
@@ -19,26 +19,26 @@
|
||||
// Constants
|
||||
/////////////
|
||||
|
||||
var LIBVERSION = '2.0.4',
|
||||
var LIBVERSION = '2.0.6',
|
||||
UA_MAX_LENGTH = 500,
|
||||
USER_AGENT = 'user-agent',
|
||||
EMPTY = '',
|
||||
UNKNOWN = '?',
|
||||
|
||||
// typeof
|
||||
FUNC_TYPE = 'function',
|
||||
UNDEF_TYPE = 'undefined',
|
||||
OBJ_TYPE = 'object',
|
||||
STR_TYPE = 'string',
|
||||
TYPEOF = {
|
||||
FUNCTION : 'function',
|
||||
OBJECT : 'object',
|
||||
STRING : 'string',
|
||||
UNDEFINED : 'undefined'
|
||||
},
|
||||
|
||||
// properties
|
||||
UA_BROWSER = 'browser',
|
||||
UA_CPU = 'cpu',
|
||||
UA_DEVICE = 'device',
|
||||
UA_ENGINE = 'engine',
|
||||
UA_OS = 'os',
|
||||
UA_RESULT = 'result',
|
||||
|
||||
BROWSER = 'browser',
|
||||
CPU = 'cpu',
|
||||
DEVICE = 'device',
|
||||
ENGINE = 'engine',
|
||||
OS = 'os',
|
||||
RESULT = 'result',
|
||||
|
||||
NAME = 'name',
|
||||
TYPE = 'type',
|
||||
VENDOR = 'vendor',
|
||||
@@ -66,16 +66,16 @@
|
||||
PLATFORM = 'platform',
|
||||
PLATFORMVER = 'platformVersion',
|
||||
BITNESS = 'bitness',
|
||||
CH_HEADER = 'sec-ch-ua',
|
||||
CH_HEADER_FULL_VER_LIST = CH_HEADER + '-full-version-list',
|
||||
CH_HEADER_ARCH = CH_HEADER + '-arch',
|
||||
CH_HEADER_BITNESS = CH_HEADER + '-' + BITNESS,
|
||||
CH_HEADER_FORM_FACTORS = CH_HEADER + '-form-factors',
|
||||
CH_HEADER_MOBILE = CH_HEADER + '-' + MOBILE,
|
||||
CH_HEADER_MODEL = CH_HEADER + '-' + MODEL,
|
||||
CH_HEADER_PLATFORM = CH_HEADER + '-' + PLATFORM,
|
||||
CH_HEADER_PLATFORM_VER = CH_HEADER_PLATFORM + '-version',
|
||||
CH_ALL_VALUES = [BRANDS, FULLVERLIST, MOBILE, MODEL, PLATFORM, PLATFORMVER, ARCHITECTURE, FORMFACTORS, BITNESS],
|
||||
CH = 'sec-ch-ua',
|
||||
CH_FULL_VER_LIST= CH + '-full-version-list',
|
||||
CH_ARCH = CH + '-arch',
|
||||
CH_BITNESS = CH + '-' + BITNESS,
|
||||
CH_FORM_FACTORS = CH + '-form-factors',
|
||||
CH_MOBILE = CH + '-' + MOBILE,
|
||||
CH_MODEL = CH + '-' + MODEL,
|
||||
CH_PLATFORM = CH + '-' + PLATFORM,
|
||||
CH_PLATFORM_VER = CH_PLATFORM + '-version',
|
||||
CH_ALL_VALUES = [BRANDS, FULLVERLIST, MOBILE, MODEL, PLATFORM, PLATFORMVER, ARCHITECTURE, FORMFACTORS, BITNESS],
|
||||
|
||||
// device vendors
|
||||
AMAZON = 'Amazon',
|
||||
@@ -114,7 +114,7 @@
|
||||
// os
|
||||
WINDOWS = 'Windows';
|
||||
|
||||
var isWindow = typeof window !== UNDEF_TYPE,
|
||||
var isWindow = typeof window !== TYPEOF.UNDEFINED,
|
||||
NAVIGATOR = (isWindow && window.navigator) ?
|
||||
window.navigator :
|
||||
undefined,
|
||||
@@ -150,7 +150,7 @@
|
||||
return enums;
|
||||
},
|
||||
has = function (str1, str2) {
|
||||
if (typeof str1 === OBJ_TYPE && str1.length > 0) {
|
||||
if (typeof str1 === TYPEOF.OBJECT && str1.length > 0) {
|
||||
for (var i in str1) {
|
||||
if (lowerize(str2) == lowerize(str1[i])) return true;
|
||||
}
|
||||
@@ -164,7 +164,7 @@
|
||||
}
|
||||
},
|
||||
isString = function (val) {
|
||||
return typeof val === STR_TYPE;
|
||||
return typeof val === TYPEOF.STRING;
|
||||
},
|
||||
itemListToArray = function (header) {
|
||||
if (!header) return undefined;
|
||||
@@ -188,8 +188,10 @@
|
||||
},
|
||||
setProps = function (arr) {
|
||||
for (var i in arr) {
|
||||
if (!arr.hasOwnProperty(i)) continue;
|
||||
|
||||
var propName = arr[i];
|
||||
if (typeof propName == OBJ_TYPE && propName.length == 2) {
|
||||
if (typeof propName == TYPEOF.OBJECT && propName.length == 2) {
|
||||
this[propName[0]] = propName[1];
|
||||
} else {
|
||||
this[propName] = undefined;
|
||||
@@ -204,10 +206,8 @@
|
||||
return strip(/\\?\"/g, str);
|
||||
},
|
||||
trim = function (str, len) {
|
||||
if (isString(str)) {
|
||||
str = strip(/^\s\s*/, str);
|
||||
return typeof len === UNDEF_TYPE ? str : str.substring(0, UA_MAX_LENGTH);
|
||||
}
|
||||
str = strip(/^\s\s*/, String(str));
|
||||
return typeof len === TYPEOF.UNDEFINED ? str : str.substring(0, len);
|
||||
};
|
||||
|
||||
///////////////
|
||||
@@ -238,9 +238,9 @@
|
||||
match = matches[++k];
|
||||
q = props[p];
|
||||
// check if given property is actually array
|
||||
if (typeof q === OBJ_TYPE && q.length > 0) {
|
||||
if (typeof q === TYPEOF.OBJECT && q.length > 0) {
|
||||
if (q.length === 2) {
|
||||
if (typeof q[1] == FUNC_TYPE) {
|
||||
if (typeof q[1] == TYPEOF.FUNCTION) {
|
||||
// assign modified match
|
||||
this[q[0]] = q[1].call(this, match);
|
||||
} else {
|
||||
@@ -249,7 +249,7 @@
|
||||
}
|
||||
} else if (q.length >= 3) {
|
||||
// Check whether q[1] FUNCTION or REGEX
|
||||
if (typeof q[1] === FUNC_TYPE && !(q[1].exec && q[1].test)) {
|
||||
if (typeof q[1] === TYPEOF.FUNCTION && !(q[1].exec && q[1].test)) {
|
||||
if (q.length > 3) {
|
||||
this[q[0]] = match ? q[1].apply(this, q.slice(2)) : undefined;
|
||||
} else {
|
||||
@@ -281,7 +281,7 @@
|
||||
|
||||
for (var i in map) {
|
||||
// check if current value is array
|
||||
if (typeof map[i] === OBJ_TYPE && map[i].length > 0) {
|
||||
if (typeof map[i] === TYPEOF.OBJECT && map[i].length > 0) {
|
||||
for (var j = 0; j < map[i].length; j++) {
|
||||
if (has(map[i][j], str)) {
|
||||
return (i === UNKNOWN) ? undefined : i;
|
||||
@@ -375,10 +375,11 @@
|
||||
/(avant|iemobile|slim(?:browser|boat|jet))[\/ ]?([\d\.]*)/i, // Avant/IEMobile/SlimBrowser/SlimBoat/Slimjet
|
||||
/(?:ms|\()(ie) ([\w\.]+)/i, // Internet Explorer
|
||||
|
||||
// Blink/Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon/LG Browser/Otter/qutebrowser/Dooble
|
||||
/(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio|(?=comodo_)?dragon|otter|dooble|(?:lg |qute)browser)\/([-\w\.]+)/i,
|
||||
// Blink/Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon/LG Browser/Otter/qutebrowser/Dooble/Palemoon
|
||||
/(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio|(?=comodo_)?dragon|otter|dooble|(?:lg |qute)browser|palemoon)\/([-\w\.]+)/i,
|
||||
// Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio/Dragon
|
||||
/(heytap|ovi|115|surf)browser\/([\d\.]+)/i, // HeyTap/Ovi/115/Surf
|
||||
/(heytap|ovi|115|surf|qwant)browser\/([\d\.]+)/i, // HeyTap/Ovi/115/Surf
|
||||
/(qwant)(?:ios|mobile)\/([\d\.]+)/i, // Qwant
|
||||
/(ecosia|weibo)(?:__| \w+@)([\d\.]+)/i // Ecosia/Weibo
|
||||
], [NAME, VERSION], [
|
||||
/quark(?:pc)?\/([-\w\.]+)/i // Quark
|
||||
@@ -447,6 +448,7 @@
|
||||
/\b(line)\/([\w\.]+)\/iab/i, // Line App for Android
|
||||
/(alipay)client\/([\w\.]+)/i, // Alipay
|
||||
/(twitter)(?:and| f.+e\/([\w\.]+))/i, // Twitter
|
||||
/(bing)(?:web|sapphire)\/([\w\.]+)/i, // Bing
|
||||
/(instagram|snapchat|klarna)[\/ ]([-\w\.]+)/i // Instagram/Snapchat/Klarna
|
||||
], [NAME, VERSION, [TYPE, INAPP]], [
|
||||
/\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS
|
||||
@@ -455,6 +457,8 @@
|
||||
], [VERSION, [NAME, 'TikTok'], [TYPE, INAPP]], [
|
||||
/\[(linkedin)app\]/i // LinkedIn App for iOS & Android
|
||||
], [NAME, [TYPE, INAPP]], [
|
||||
/(zalo(?:app)?)[\/\sa-z]*([\w\.-]+)/i // Zalo
|
||||
], [[NAME, /(.+)/, 'Zalo'], VERSION, [TYPE, INAPP]], [
|
||||
|
||||
/(chromium)[\/ ]([-\w\.]+)/i // Chromium
|
||||
], [NAME, VERSION], [
|
||||
@@ -502,10 +506,10 @@
|
||||
/(swiftfox)/i, // Swiftfox
|
||||
/(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror)[\/ ]?([\w\.\+]+)/i,
|
||||
// IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror
|
||||
/(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\/([-\w\.]+)$/i,
|
||||
/(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|basilisk|waterfox)\/([-\w\.]+)$/i,
|
||||
// Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix
|
||||
/(firefox)\/([\w\.]+)/i, // Other Firefox-based
|
||||
/(mozilla)\/([\w\.]+) .+rv\:.+gecko\/\d+/i, // Mozilla
|
||||
/(mozilla)\/([\w\.]+(?= .+rv\:.+gecko\/\d+)|[0-4][\w\.]+(?!.+compatible))/i, // Mozilla
|
||||
|
||||
// Other
|
||||
/(amaya|dillo|doris|icab|ladybird|lynx|mosaic|netsurf|obigo|polaris|w3m|(?:go|ice|up)[\. ]?browser)[-\/ ]?v?([\w\.]+)/i,
|
||||
@@ -536,15 +540,17 @@
|
||||
/( (ce|mobile); ppc;|\/[\w\.]+arm\b)/i
|
||||
], [[ARCHITECTURE, 'arm']], [
|
||||
|
||||
/((ppc|powerpc)(64)?)( mac|;|\))/i // PowerPC
|
||||
], [[ARCHITECTURE, /ower/, EMPTY, lowerize]], [
|
||||
|
||||
/ sun4\w[;\)]/i // SPARC
|
||||
], [[ARCHITECTURE, 'sparc']], [
|
||||
|
||||
/\b(avr32|ia64(?=;)|68k(?=\))|\barm(?=v([1-7]|[5-7]1)l?|;|eabi)|(irix|mips|sparc)(64)?\b|pa-risc)/i
|
||||
// IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC
|
||||
], [[ARCHITECTURE, lowerize]]
|
||||
/\b(avr32|ia64(?=;)|68k(?=\))|\barm(?=v([1-7]|[5-7]1)l?|;|eabi)|(irix|mips|sparc)(64)?\b|pa-risc)/i,
|
||||
/((ppc|powerpc)(64)?)( mac|;|\))/i, // PowerPC
|
||||
/(?:osf1|[freopnt]{3,4}bsd) (alpha)/i // Alpha
|
||||
], [[ARCHITECTURE, /ower/, EMPTY, lowerize]], [
|
||||
/mc680.0/i
|
||||
], [[ARCHITECTURE, '68k']], [
|
||||
/winnt.+\[axp/i
|
||||
], [[ARCHITECTURE, 'alpha']]
|
||||
],
|
||||
|
||||
device : [[
|
||||
@@ -562,11 +568,10 @@
|
||||
], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [
|
||||
|
||||
// Apple
|
||||
/(?:\/|\()(ip(?:hone|od)[\w, ]*)(?:\/|;)/i // iPod/iPhone
|
||||
/(?:\/|\()(ip(?:hone|od)[\w, ]*)[\/\);]/i // iPod/iPhone
|
||||
], [MODEL, [VENDOR, APPLE], [TYPE, MOBILE]], [
|
||||
/\((ipad);[-\w\),; ]+apple/i, // iPad
|
||||
/applecoremedia\/[\w\.]+ \((ipad)/i,
|
||||
/\b(ipad)\d\d?,\d\d?[;\]].+ios/i
|
||||
/\b(?:ios|apple\w+)\/.+[\(\/](ipad)/i, // iPad
|
||||
/\b(ipad)[\d,]*[;\] ].+(mac |i(pad)?)os/i
|
||||
], [MODEL, [VENDOR, APPLE], [TYPE, TABLET]], [
|
||||
/(macintosh);/i
|
||||
], [MODEL, [VENDOR, APPLE]], [
|
||||
@@ -584,13 +589,13 @@
|
||||
// Huawei
|
||||
/\b((?:ag[rs][2356]?k?|bah[234]?|bg[2o]|bt[kv]|cmr|cpn|db[ry]2?|jdn2|got|kob2?k?|mon|pce|scm|sht?|[tw]gr|vrd)-[ad]?[lw][0125][09]b?|605hw|bg2-u03|(?:gem|fdr|m2|ple|t1)-[7a]0[1-4][lu]|t1-a2[13][lw]|mediapad[\w\. ]*(?= bui|\)))\b(?!.+d\/s)/i
|
||||
], [MODEL, [VENDOR, HUAWEI], [TYPE, TABLET]], [
|
||||
/(?:huawei)([-\w ]+)[;\)]/i,
|
||||
/\b(nexus 6p|\w{2,4}e?-[atu]?[ln][\dx][012359c][adn]?)\b(?!.+d\/s)/i
|
||||
/(?:huawei) ?([-\w ]+)[;\)]/i,
|
||||
/\b(nexus 6p|\w{2,4}e?-[atu]?[ln][\dx][\dc][adnt]?)\b(?!.+d\/s)/i
|
||||
], [MODEL, [VENDOR, HUAWEI], [TYPE, MOBILE]], [
|
||||
|
||||
// Xiaomi
|
||||
/oid[^\)]+; (2[\dbc]{4}(182|283|rp\w{2})[cgl]|m2105k81a?c)(?: bui|\))/i,
|
||||
/\b((?:red)?mi[-_ ]?pad[\w- ]*)(?: bui|\))/i // Mi Pad tablets
|
||||
/\b(?:xiao)?((?:red)?mi[-_ ]?pad[\w- ]*)(?: bui|\))/i // Mi Pad tablets
|
||||
],[[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, TABLET]], [
|
||||
|
||||
/\b(poco[\w ]+|m2\d{3}j\d\d[a-z]{2})(?: bui|\))/i, // Xiaomi POCO
|
||||
@@ -598,7 +603,7 @@
|
||||
/\b(hm[-_ ]?note?[_ ]?(?:\d\w)?) bui/i, // Xiaomi Hongmi
|
||||
/\b(redmi[\-_ ]?(?:note|k)?[\w_ ]+)(?: bui|\))/i, // Xiaomi Redmi
|
||||
/oid[^\)]+; (m?[12][0-389][01]\w{3,6}[c-y])( bui|; wv|\))/i, // Xiaomi Redmi 'numeric' models
|
||||
/\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note lte|max|cc)?[_ ]?(?:\d?\w?)[_ ]?(?:plus|se|lite|pro)?)(?: bui|\))/i, // Xiaomi Mi
|
||||
/\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note|max|cc)?[_ ]?(?:\d{0,2}\w?)[_ ]?(?:plus|se|lite|pro)?( 5g|lte)?)(?: bui|\))/i, // Xiaomi Mi
|
||||
/ ([\w ]+) miui\/v?\d/i
|
||||
], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [
|
||||
|
||||
@@ -654,7 +659,7 @@
|
||||
/(nokia) (t[12][01])/i
|
||||
], [VENDOR, MODEL, [TYPE, TABLET]], [
|
||||
/(?:maemo|nokia).*(n900|lumia \d+|rm-\d+)/i,
|
||||
/nokia[-_ ]?(([-\w\. ]*))/i
|
||||
/nokia[-_ ]?(([-\w\. ]*?))( bui|\)|;|\/)/i
|
||||
], [[MODEL, /_/g, ' '], [TYPE, MOBILE], [VENDOR, 'Nokia']], [
|
||||
|
||||
// Google
|
||||
@@ -685,7 +690,7 @@
|
||||
/(playbook);[-\w\),; ]+(rim)/i // BlackBerry PlayBook
|
||||
], [MODEL, VENDOR, [TYPE, TABLET]], [
|
||||
/\b((?:bb[a-f]|st[hv])100-\d)/i,
|
||||
/\(bb10; (\w+)/i // BlackBerry 10
|
||||
/(?:blackberry|\(bb10;) (\w+)/i
|
||||
], [MODEL, [VENDOR, BLACKBERRY], [TYPE, MOBILE]], [
|
||||
|
||||
// Asus
|
||||
@@ -765,10 +770,13 @@
|
||||
|
||||
/(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus(?! zenw)|dell|jolla|meizu|motorola|polytron|tecno|micromax|advan)[-_ ]?([-\w]*)/i,
|
||||
// BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron/Tecno/Micromax/Advan
|
||||
/; (blu|hmd|imo|infinix|lava|oneplus|tcl)[_ ]([\w\+ ]+?)(?: bui|\)|; r)/i, // BLU/HMD/IMO/Infinix/Lava/OnePlus/TCL
|
||||
// BLU/HMD/IMO/Infinix/Lava/OnePlus/TCL/Wiko
|
||||
/; (blu|hmd|imo|infinix|lava|oneplus|tcl|wiko)[_ ]([\w\+ ]+?)(?: bui|\)|; r)/i,
|
||||
/(hp) ([\w ]+\w)/i, // HP iPAQ
|
||||
/(microsoft); (lumia[\w ]+)/i, // Microsoft Lumia
|
||||
/(oppo) ?([\w ]+) bui/i // OPPO
|
||||
/(oppo) ?([\w ]+) bui/i, // OPPO
|
||||
/(hisense) ([ehv][\w ]+)\)/i, // Hisense
|
||||
/droid[^;]+; (philips)[_ ]([sv-x][\d]{3,4}[xz]?)/i // Philips
|
||||
], [VENDOR, MODEL, [TYPE, MOBILE]], [
|
||||
|
||||
/(kobo)\s(ereader|touch)/i, // Kobo
|
||||
@@ -795,6 +803,7 @@
|
||||
// SMARTTVS
|
||||
///////////////////
|
||||
|
||||
/(philips)[\w ]+tv/i, // Philips
|
||||
/smart-tv.+(samsung)/i // Samsung
|
||||
], [VENDOR, [TYPE, SMARTTV]], [
|
||||
/hbbtv.+maple;(\d+)/i
|
||||
@@ -832,11 +841,6 @@
|
||||
/\b(roku)[\dx]*[\)\/]((?:dvp-)?[\d\.]*)/i, // Roku
|
||||
/hbbtv\/\d+\.\d+\.\d+ +\([\w\+ ]*; *([\w\d][^;]*);([^;]*)/i // HbbTV devices
|
||||
], [[VENDOR, /.+\/(\w+)/, '$1', strMapper, {'LG':'lge'}], [MODEL, trim], [TYPE, SMARTTV]], [
|
||||
// SmartTV from Unidentified Vendors
|
||||
/droid.+; ([\w- ]+) (?:android tv|smart[- ]?tv)/i
|
||||
], [MODEL, [TYPE, SMARTTV]], [
|
||||
/\b(android tv|smart[- ]?tv|opera tv|tv; rv:|large screen[\w ]+safari)\b/i
|
||||
], [[TYPE, SMARTTV]], [
|
||||
|
||||
///////////////////
|
||||
// CONSOLES
|
||||
@@ -883,7 +887,7 @@
|
||||
|
||||
/droid.+; (glass) \d/i // Google Glass
|
||||
], [MODEL, [VENDOR, GOOGLE], [TYPE, XR]], [
|
||||
/(pico) (4|neo3(?: link|pro)?)/i // Pico
|
||||
/(pico) ([\w ]+) os\d/i // Pico
|
||||
], [VENDOR, MODEL, [TYPE, XR]], [
|
||||
/(quest( \d| pro)?s?).+vr/i // Meta Quest
|
||||
], [MODEL, [VENDOR, FACEBOOK], [TYPE, XR]], [
|
||||
@@ -907,7 +911,11 @@
|
||||
// MIXED (GENERIC)
|
||||
///////////////////
|
||||
|
||||
/droid .+?; ([^;]+?)(?: bui|; wv\)|\) applew).+?(mobile|vr|\d) safari/i
|
||||
/droid.+; ([\w- ]+) (4k|android|smart|google)[- ]?tv/i // Unidentifiable SmartTV
|
||||
], [MODEL, [TYPE, SMARTTV]], [
|
||||
/\b((4k|android|smart|opera)[- ]?tv|tv; rv:|large screen[\w ]+safari)\b/i
|
||||
], [[TYPE, SMARTTV]], [
|
||||
/droid .+?; ([^;]+?)(?: bui|; wv\)|\) applew|; hmsc).+?(mobile|vr|\d) safari/i
|
||||
], [MODEL, [TYPE, strMapper, { 'mobile' : 'Mobile', 'xr' : 'VR', '*' : TABLET }]], [
|
||||
/\b((tablet|tab)[;\/]|focus\/\d(?!.+mobile))/i // Unidentifiable Tablet
|
||||
], [[TYPE, TABLET]], [
|
||||
@@ -960,7 +968,7 @@
|
||||
|
||||
// iOS/macOS
|
||||
/[adehimnop]{4,7}\b(?:.*os ([\w]+) like mac|; opera)/i, // iOS
|
||||
/(?:ios;fbsv\/|iphone.+ios[\/ ])([\d\.]+)/i,
|
||||
/(?:ios;fbsv|ios(?=.+ip(?:ad|hone))|ip(?:ad|hone)(?: |.+i(?:pad)?)os)[\/ ]([\w\.]+)/i,
|
||||
/cfnetwork\/.+darwin/i
|
||||
], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [
|
||||
/(mac os x) ?([\w\. ]*)/i,
|
||||
@@ -1045,27 +1053,27 @@
|
||||
var defaultProps = (function () {
|
||||
var props = { init : {}, isIgnore : {}, isIgnoreRgx : {}, toString : {}};
|
||||
setProps.call(props.init, [
|
||||
[UA_BROWSER, [NAME, VERSION, MAJOR, TYPE]],
|
||||
[UA_CPU, [ARCHITECTURE]],
|
||||
[UA_DEVICE, [TYPE, MODEL, VENDOR]],
|
||||
[UA_ENGINE, [NAME, VERSION]],
|
||||
[UA_OS, [NAME, VERSION]]
|
||||
[BROWSER, [NAME, VERSION, MAJOR, TYPE]],
|
||||
[CPU, [ARCHITECTURE]],
|
||||
[DEVICE, [TYPE, MODEL, VENDOR]],
|
||||
[ENGINE, [NAME, VERSION]],
|
||||
[OS, [NAME, VERSION]]
|
||||
]);
|
||||
setProps.call(props.isIgnore, [
|
||||
[UA_BROWSER, [VERSION, MAJOR]],
|
||||
[UA_ENGINE, [VERSION]],
|
||||
[UA_OS, [VERSION]]
|
||||
[BROWSER, [VERSION, MAJOR]],
|
||||
[ENGINE, [VERSION]],
|
||||
[OS, [VERSION]]
|
||||
]);
|
||||
setProps.call(props.isIgnoreRgx, [
|
||||
[UA_BROWSER, / ?browser$/i],
|
||||
[UA_OS, / ?os$/i]
|
||||
[BROWSER, / ?browser$/i],
|
||||
[OS, / ?os$/i]
|
||||
]);
|
||||
setProps.call(props.toString, [
|
||||
[UA_BROWSER, [NAME, VERSION]],
|
||||
[UA_CPU, [ARCHITECTURE]],
|
||||
[UA_DEVICE, [VENDOR, MODEL]],
|
||||
[UA_ENGINE, [NAME, VERSION]],
|
||||
[UA_OS, [NAME, VERSION]]
|
||||
[BROWSER, [NAME, VERSION]],
|
||||
[CPU, [ARCHITECTURE]],
|
||||
[DEVICE, [VENDOR, MODEL]],
|
||||
[ENGINE, [NAME, VERSION]],
|
||||
[OS, [NAME, VERSION]]
|
||||
]);
|
||||
return props;
|
||||
})();
|
||||
@@ -1109,14 +1117,14 @@
|
||||
return item.detectFeature().get();
|
||||
};
|
||||
|
||||
if (itemType != UA_RESULT) {
|
||||
if (itemType != RESULT) {
|
||||
IData.prototype.is = function (strToCheck) {
|
||||
var is = false;
|
||||
for (var i in this) {
|
||||
if (this.hasOwnProperty(i) && !has(is_ignoreProps, i) && lowerize(is_ignoreRgx ? strip(is_ignoreRgx, this[i]) : this[i]) == lowerize(is_ignoreRgx ? strip(is_ignoreRgx, strToCheck) : strToCheck)) {
|
||||
is = true;
|
||||
if (strToCheck != UNDEF_TYPE) break;
|
||||
} else if (strToCheck == UNDEF_TYPE && is) {
|
||||
if (strToCheck != TYPEOF.UNDEFINED) break;
|
||||
} else if (strToCheck == TYPEOF.UNDEFINED && is) {
|
||||
is = !is;
|
||||
break;
|
||||
}
|
||||
@@ -1126,11 +1134,11 @@
|
||||
IData.prototype.toString = function () {
|
||||
var str = EMPTY;
|
||||
for (var i in toString_props) {
|
||||
if (typeof(this[toString_props[i]]) !== UNDEF_TYPE) {
|
||||
if (typeof(this[toString_props[i]]) !== TYPEOF.UNDEFINED) {
|
||||
str += (str ? ' ' : EMPTY) + this[toString_props[i]];
|
||||
}
|
||||
}
|
||||
return str || UNDEF_TYPE;
|
||||
return str || TYPEOF.UNDEFINED;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1166,19 +1174,19 @@
|
||||
setProps.call(this, CH_ALL_VALUES);
|
||||
if (isHttpUACH) {
|
||||
setProps.call(this, [
|
||||
[BRANDS, itemListToArray(uach[CH_HEADER])],
|
||||
[FULLVERLIST, itemListToArray(uach[CH_HEADER_FULL_VER_LIST])],
|
||||
[MOBILE, /\?1/.test(uach[CH_HEADER_MOBILE])],
|
||||
[MODEL, stripQuotes(uach[CH_HEADER_MODEL])],
|
||||
[PLATFORM, stripQuotes(uach[CH_HEADER_PLATFORM])],
|
||||
[PLATFORMVER, stripQuotes(uach[CH_HEADER_PLATFORM_VER])],
|
||||
[ARCHITECTURE, stripQuotes(uach[CH_HEADER_ARCH])],
|
||||
[FORMFACTORS, itemListToArray(uach[CH_HEADER_FORM_FACTORS])],
|
||||
[BITNESS, stripQuotes(uach[CH_HEADER_BITNESS])]
|
||||
[BRANDS, itemListToArray(uach[CH])],
|
||||
[FULLVERLIST, itemListToArray(uach[CH_FULL_VER_LIST])],
|
||||
[MOBILE, /\?1/.test(uach[CH_MOBILE])],
|
||||
[MODEL, stripQuotes(uach[CH_MODEL])],
|
||||
[PLATFORM, stripQuotes(uach[CH_PLATFORM])],
|
||||
[PLATFORMVER, stripQuotes(uach[CH_PLATFORM_VER])],
|
||||
[ARCHITECTURE, stripQuotes(uach[CH_ARCH])],
|
||||
[FORMFACTORS, itemListToArray(uach[CH_FORM_FACTORS])],
|
||||
[BITNESS, stripQuotes(uach[CH_BITNESS])]
|
||||
]);
|
||||
} else {
|
||||
for (var prop in uach) {
|
||||
if(this.hasOwnProperty(prop) && typeof uach[prop] !== UNDEF_TYPE) this[prop] = uach[prop];
|
||||
if(this.hasOwnProperty(prop) && typeof uach[prop] !== TYPEOF.UNDEFINED) this[prop] = uach[prop];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1203,30 +1211,30 @@
|
||||
this.detectFeature = function () {
|
||||
if (NAVIGATOR && NAVIGATOR.userAgent == this.ua) {
|
||||
switch (this.itemType) {
|
||||
case UA_BROWSER:
|
||||
case BROWSER:
|
||||
// Brave-specific detection
|
||||
if (NAVIGATOR.brave && typeof NAVIGATOR.brave.isBrave == FUNC_TYPE) {
|
||||
if (NAVIGATOR.brave && typeof NAVIGATOR.brave.isBrave == TYPEOF.FUNCTION) {
|
||||
this.set(NAME, 'Brave');
|
||||
}
|
||||
break;
|
||||
case UA_DEVICE:
|
||||
case DEVICE:
|
||||
// Chrome-specific detection: check for 'mobile' value of navigator.userAgentData
|
||||
if (!this.get(TYPE) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[MOBILE]) {
|
||||
this.set(TYPE, MOBILE);
|
||||
}
|
||||
// iPadOS-specific detection: identified as Mac, but has some iOS-only properties
|
||||
if (this.get(MODEL) == 'Macintosh' && NAVIGATOR && typeof NAVIGATOR.standalone !== UNDEF_TYPE && NAVIGATOR.maxTouchPoints && NAVIGATOR.maxTouchPoints > 2) {
|
||||
if (this.get(MODEL) == 'Macintosh' && NAVIGATOR && typeof NAVIGATOR.standalone !== TYPEOF.UNDEFINED && NAVIGATOR.maxTouchPoints && NAVIGATOR.maxTouchPoints > 2) {
|
||||
this.set(MODEL, 'iPad')
|
||||
.set(TYPE, TABLET);
|
||||
}
|
||||
break;
|
||||
case UA_OS:
|
||||
case OS:
|
||||
// Chrome-specific detection: check for 'platform' value of navigator.userAgentData
|
||||
if (!this.get(NAME) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[PLATFORM]) {
|
||||
this.set(NAME, NAVIGATOR_UADATA[PLATFORM]);
|
||||
}
|
||||
break;
|
||||
case UA_RESULT:
|
||||
case RESULT:
|
||||
var data = this.data;
|
||||
var detect = function (itemType) {
|
||||
return data[itemType]
|
||||
@@ -1234,22 +1242,33 @@
|
||||
.detectFeature()
|
||||
.get();
|
||||
};
|
||||
this.set(UA_BROWSER, detect(UA_BROWSER))
|
||||
.set(UA_CPU, detect(UA_CPU))
|
||||
.set(UA_DEVICE, detect(UA_DEVICE))
|
||||
.set(UA_ENGINE, detect(UA_ENGINE))
|
||||
.set(UA_OS, detect(UA_OS));
|
||||
this.set(BROWSER, detect(BROWSER))
|
||||
.set(CPU, detect(CPU))
|
||||
.set(DEVICE, detect(DEVICE))
|
||||
.set(ENGINE, detect(ENGINE))
|
||||
.set(OS, detect(OS));
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
this.parseUA = function () {
|
||||
if (this.itemType != UA_RESULT) {
|
||||
if (this.itemType != RESULT) {
|
||||
rgxMapper.call(this.data, this.ua, this.rgxMap);
|
||||
}
|
||||
if (this.itemType == UA_BROWSER) {
|
||||
this.set(MAJOR, majorize(this.get(VERSION)));
|
||||
switch (this.itemType) {
|
||||
case BROWSER:
|
||||
this.set(MAJOR, majorize(this.get(VERSION)));
|
||||
break;
|
||||
case OS:
|
||||
if (this.get(NAME) == 'iOS' && this.get(VERSION) == '18.6') {
|
||||
// Based on the assumption that iOS version is tightly coupled with Safari version
|
||||
var realVersion = /\) Version\/([\d\.]+)/.exec(this.ua); // Get Safari version
|
||||
if (realVersion && parseInt(realVersion[1].substring(0,2), 10) >= 26) {
|
||||
this.set(VERSION, realVersion[1]); // Set as iOS version
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return this;
|
||||
};
|
||||
@@ -1259,14 +1278,14 @@
|
||||
rgxMap = this.rgxMap;
|
||||
|
||||
switch (this.itemType) {
|
||||
case UA_BROWSER:
|
||||
case UA_ENGINE:
|
||||
case BROWSER:
|
||||
case ENGINE:
|
||||
var brands = uaCH[FULLVERLIST] || uaCH[BRANDS], prevName;
|
||||
if (brands) {
|
||||
for (var i in brands) {
|
||||
for (var i=0; i<brands.length; i++) {
|
||||
var brandName = brands[i].brand || brands[i],
|
||||
brandVersion = brands[i].version;
|
||||
if (this.itemType == UA_BROWSER &&
|
||||
if (this.itemType == BROWSER &&
|
||||
!/not.a.brand/i.test(brandName) &&
|
||||
(!prevName ||
|
||||
(/Chrom/.test(prevName) && brandName != CHROMIUM) ||
|
||||
@@ -1281,20 +1300,20 @@
|
||||
}
|
||||
prevName = brandName;
|
||||
}
|
||||
if (this.itemType == UA_ENGINE && brandName == CHROMIUM) {
|
||||
if (this.itemType == ENGINE && brandName == CHROMIUM) {
|
||||
this.set(VERSION, brandVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case UA_CPU:
|
||||
case CPU:
|
||||
var archName = uaCH[ARCHITECTURE];
|
||||
if (archName) {
|
||||
if (archName && uaCH[BITNESS] == '64') archName += '64';
|
||||
rgxMapper.call(this.data, archName + ';', rgxMap);
|
||||
}
|
||||
break;
|
||||
case UA_DEVICE:
|
||||
case DEVICE:
|
||||
if (uaCH[MOBILE]) {
|
||||
this.set(TYPE, MOBILE);
|
||||
}
|
||||
@@ -1324,7 +1343,7 @@
|
||||
this.set(TYPE, ff);
|
||||
}
|
||||
break;
|
||||
case UA_OS:
|
||||
case OS:
|
||||
var osName = uaCH[PLATFORM];
|
||||
if(osName) {
|
||||
var osVersion = uaCH[PLATFORMVER];
|
||||
@@ -1338,7 +1357,7 @@
|
||||
.set(VERSION, undefined);
|
||||
}
|
||||
break;
|
||||
case UA_RESULT:
|
||||
case RESULT:
|
||||
var data = this.data;
|
||||
var parse = function (itemType) {
|
||||
return data[itemType]
|
||||
@@ -1347,11 +1366,11 @@
|
||||
.parseCH()
|
||||
.get();
|
||||
};
|
||||
this.set(UA_BROWSER, parse(UA_BROWSER))
|
||||
.set(UA_CPU, parse(UA_CPU))
|
||||
.set(UA_DEVICE, parse(UA_DEVICE))
|
||||
.set(UA_ENGINE, parse(UA_ENGINE))
|
||||
.set(UA_OS, parse(UA_OS));
|
||||
this.set(BROWSER, parse(BROWSER))
|
||||
.set(CPU, parse(CPU))
|
||||
.set(DEVICE, parse(DEVICE))
|
||||
.set(ENGINE, parse(ENGINE))
|
||||
.set(OS, parse(OS));
|
||||
}
|
||||
return this;
|
||||
};
|
||||
@@ -1369,9 +1388,9 @@
|
||||
|
||||
function UAParser (ua, extensions, headers) {
|
||||
|
||||
if (typeof ua === OBJ_TYPE) {
|
||||
if (typeof ua === TYPEOF.OBJECT) {
|
||||
if (isExtensions(ua, true)) {
|
||||
if (typeof extensions === OBJ_TYPE) {
|
||||
if (typeof extensions === TYPEOF.OBJECT) {
|
||||
headers = extensions; // case UAParser(extensions, headers)
|
||||
}
|
||||
extensions = ua; // case UAParser(extensions)
|
||||
@@ -1380,23 +1399,34 @@
|
||||
extensions = undefined;
|
||||
}
|
||||
ua = undefined;
|
||||
} else if (typeof ua === STR_TYPE && !isExtensions(extensions, true)) {
|
||||
} else if (typeof ua === TYPEOF.STRING && !isExtensions(extensions, true)) {
|
||||
headers = extensions; // case UAParser(ua, headers)
|
||||
extensions = undefined;
|
||||
}
|
||||
|
||||
// Convert Headers object into a plain object
|
||||
if (headers && typeof headers.append === FUNC_TYPE) {
|
||||
var kv = {};
|
||||
headers.forEach(function (v, k) { kv[k] = v; });
|
||||
headers = kv;
|
||||
if (headers) {
|
||||
if (typeof headers.append === TYPEOF.FUNCTION) {
|
||||
// Convert Headers object into a plain object
|
||||
var kv = {};
|
||||
headers.forEach(function (v, k) { kv[String(k).toLowerCase()] = v; });
|
||||
headers = kv;
|
||||
} else {
|
||||
// Normalize headers field name into lowercase
|
||||
var normalized = {};
|
||||
for (var header in headers) {
|
||||
if (headers.hasOwnProperty(header)) {
|
||||
normalized[String(header).toLowerCase()] = headers[header];
|
||||
}
|
||||
}
|
||||
headers = normalized;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(this instanceof UAParser)) {
|
||||
return new UAParser(ua, extensions, headers).getResult();
|
||||
}
|
||||
|
||||
var userAgent = typeof ua === STR_TYPE ? ua : // Passed user-agent string
|
||||
var userAgent = typeof ua === TYPEOF.STRING ? ua : // Passed user-agent string
|
||||
(headers && headers[USER_AGENT] ? headers[USER_AGENT] : // User-Agent from passed headers
|
||||
((NAVIGATOR && NAVIGATOR.userAgent) ? NAVIGATOR.userAgent : // navigator.userAgent
|
||||
EMPTY)), // empty string
|
||||
@@ -1407,15 +1437,15 @@
|
||||
defaultRegexes,
|
||||
|
||||
createItemFunc = function (itemType) {
|
||||
if (itemType == UA_RESULT) {
|
||||
if (itemType == RESULT) {
|
||||
return function () {
|
||||
return new UAItem(itemType, userAgent, regexMap, httpUACH)
|
||||
.set('ua', userAgent)
|
||||
.set(UA_BROWSER, this.getBrowser())
|
||||
.set(UA_CPU, this.getCPU())
|
||||
.set(UA_DEVICE, this.getDevice())
|
||||
.set(UA_ENGINE, this.getEngine())
|
||||
.set(UA_OS, this.getOS())
|
||||
.set(BROWSER, this.getBrowser())
|
||||
.set(CPU, this.getCPU())
|
||||
.set(DEVICE, this.getDevice())
|
||||
.set(ENGINE, this.getEngine())
|
||||
.set(OS, this.getOS())
|
||||
.get();
|
||||
};
|
||||
} else {
|
||||
@@ -1429,16 +1459,15 @@
|
||||
|
||||
// public methods
|
||||
setProps.call(this, [
|
||||
['getBrowser', createItemFunc(UA_BROWSER)],
|
||||
['getCPU', createItemFunc(UA_CPU)],
|
||||
['getDevice', createItemFunc(UA_DEVICE)],
|
||||
['getEngine', createItemFunc(UA_ENGINE)],
|
||||
['getOS', createItemFunc(UA_OS)],
|
||||
['getResult', createItemFunc(UA_RESULT)],
|
||||
['getBrowser', createItemFunc(BROWSER)],
|
||||
['getCPU', createItemFunc(CPU)],
|
||||
['getDevice', createItemFunc(DEVICE)],
|
||||
['getEngine', createItemFunc(ENGINE)],
|
||||
['getOS', createItemFunc(OS)],
|
||||
['getResult', createItemFunc(RESULT)],
|
||||
['getUA', function () { return userAgent; }],
|
||||
['setUA', function (ua) {
|
||||
if (isString(ua))
|
||||
userAgent = ua.length > UA_MAX_LENGTH ? trim(ua, UA_MAX_LENGTH) : ua;
|
||||
if (isString(ua)) userAgent = trim(ua, UA_MAX_LENGTH);
|
||||
return this;
|
||||
}]
|
||||
])
|
||||
@@ -1458,15 +1487,15 @@
|
||||
//////////
|
||||
|
||||
// check js environment
|
||||
if (typeof exports !== UNDEF_TYPE) {
|
||||
if (typeof exports !== TYPEOF.UNDEFINED) {
|
||||
// nodejs env
|
||||
if (typeof module !== UNDEF_TYPE && module.exports) {
|
||||
if (typeof module !== TYPEOF.UNDEFINED && module.exports) {
|
||||
exports = module.exports = UAParser;
|
||||
}
|
||||
exports.UAParser = UAParser;
|
||||
} else {
|
||||
// requirejs env (optional)
|
||||
if (typeof define === FUNC_TYPE && define.amd) {
|
||||
if (typeof define === TYPEOF.FUNCTION && define.amd) {
|
||||
define(function () {
|
||||
return UAParser;
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// Source: /src/main/ua-parser.js
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/* UAParser.js v2.0.4
|
||||
/* UAParser.js v2.0.6
|
||||
Copyright © 2012-2025 Faisal Salman <f@faisalman.com>
|
||||
UAParser.js PRO Personal License *//*
|
||||
Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.
|
||||
@@ -21,26 +21,26 @@
|
||||
// Constants
|
||||
/////////////
|
||||
|
||||
var LIBVERSION = '2.0.4',
|
||||
var LIBVERSION = '2.0.6',
|
||||
UA_MAX_LENGTH = 500,
|
||||
USER_AGENT = 'user-agent',
|
||||
EMPTY = '',
|
||||
UNKNOWN = '?',
|
||||
|
||||
// typeof
|
||||
FUNC_TYPE = 'function',
|
||||
UNDEF_TYPE = 'undefined',
|
||||
OBJ_TYPE = 'object',
|
||||
STR_TYPE = 'string',
|
||||
TYPEOF = {
|
||||
FUNCTION : 'function',
|
||||
OBJECT : 'object',
|
||||
STRING : 'string',
|
||||
UNDEFINED : 'undefined'
|
||||
},
|
||||
|
||||
// properties
|
||||
UA_BROWSER = 'browser',
|
||||
UA_CPU = 'cpu',
|
||||
UA_DEVICE = 'device',
|
||||
UA_ENGINE = 'engine',
|
||||
UA_OS = 'os',
|
||||
UA_RESULT = 'result',
|
||||
|
||||
BROWSER = 'browser',
|
||||
CPU = 'cpu',
|
||||
DEVICE = 'device',
|
||||
ENGINE = 'engine',
|
||||
OS = 'os',
|
||||
RESULT = 'result',
|
||||
|
||||
NAME = 'name',
|
||||
TYPE = 'type',
|
||||
VENDOR = 'vendor',
|
||||
@@ -68,16 +68,16 @@
|
||||
PLATFORM = 'platform',
|
||||
PLATFORMVER = 'platformVersion',
|
||||
BITNESS = 'bitness',
|
||||
CH_HEADER = 'sec-ch-ua',
|
||||
CH_HEADER_FULL_VER_LIST = CH_HEADER + '-full-version-list',
|
||||
CH_HEADER_ARCH = CH_HEADER + '-arch',
|
||||
CH_HEADER_BITNESS = CH_HEADER + '-' + BITNESS,
|
||||
CH_HEADER_FORM_FACTORS = CH_HEADER + '-form-factors',
|
||||
CH_HEADER_MOBILE = CH_HEADER + '-' + MOBILE,
|
||||
CH_HEADER_MODEL = CH_HEADER + '-' + MODEL,
|
||||
CH_HEADER_PLATFORM = CH_HEADER + '-' + PLATFORM,
|
||||
CH_HEADER_PLATFORM_VER = CH_HEADER_PLATFORM + '-version',
|
||||
CH_ALL_VALUES = [BRANDS, FULLVERLIST, MOBILE, MODEL, PLATFORM, PLATFORMVER, ARCHITECTURE, FORMFACTORS, BITNESS],
|
||||
CH = 'sec-ch-ua',
|
||||
CH_FULL_VER_LIST= CH + '-full-version-list',
|
||||
CH_ARCH = CH + '-arch',
|
||||
CH_BITNESS = CH + '-' + BITNESS,
|
||||
CH_FORM_FACTORS = CH + '-form-factors',
|
||||
CH_MOBILE = CH + '-' + MOBILE,
|
||||
CH_MODEL = CH + '-' + MODEL,
|
||||
CH_PLATFORM = CH + '-' + PLATFORM,
|
||||
CH_PLATFORM_VER = CH_PLATFORM + '-version',
|
||||
CH_ALL_VALUES = [BRANDS, FULLVERLIST, MOBILE, MODEL, PLATFORM, PLATFORMVER, ARCHITECTURE, FORMFACTORS, BITNESS],
|
||||
|
||||
// device vendors
|
||||
AMAZON = 'Amazon',
|
||||
@@ -116,7 +116,7 @@
|
||||
// os
|
||||
WINDOWS = 'Windows';
|
||||
|
||||
var isWindow = typeof window !== UNDEF_TYPE,
|
||||
var isWindow = typeof window !== TYPEOF.UNDEFINED,
|
||||
NAVIGATOR = (isWindow && window.navigator) ?
|
||||
window.navigator :
|
||||
undefined,
|
||||
@@ -152,7 +152,7 @@
|
||||
return enums;
|
||||
},
|
||||
has = function (str1, str2) {
|
||||
if (typeof str1 === OBJ_TYPE && str1.length > 0) {
|
||||
if (typeof str1 === TYPEOF.OBJECT && str1.length > 0) {
|
||||
for (var i in str1) {
|
||||
if (lowerize(str2) == lowerize(str1[i])) return true;
|
||||
}
|
||||
@@ -166,7 +166,7 @@
|
||||
}
|
||||
},
|
||||
isString = function (val) {
|
||||
return typeof val === STR_TYPE;
|
||||
return typeof val === TYPEOF.STRING;
|
||||
},
|
||||
itemListToArray = function (header) {
|
||||
if (!header) return undefined;
|
||||
@@ -190,8 +190,10 @@
|
||||
},
|
||||
setProps = function (arr) {
|
||||
for (var i in arr) {
|
||||
if (!arr.hasOwnProperty(i)) continue;
|
||||
|
||||
var propName = arr[i];
|
||||
if (typeof propName == OBJ_TYPE && propName.length == 2) {
|
||||
if (typeof propName == TYPEOF.OBJECT && propName.length == 2) {
|
||||
this[propName[0]] = propName[1];
|
||||
} else {
|
||||
this[propName] = undefined;
|
||||
@@ -206,10 +208,8 @@
|
||||
return strip(/\\?\"/g, str);
|
||||
},
|
||||
trim = function (str, len) {
|
||||
if (isString(str)) {
|
||||
str = strip(/^\s\s*/, str);
|
||||
return typeof len === UNDEF_TYPE ? str : str.substring(0, UA_MAX_LENGTH);
|
||||
}
|
||||
str = strip(/^\s\s*/, String(str));
|
||||
return typeof len === TYPEOF.UNDEFINED ? str : str.substring(0, len);
|
||||
};
|
||||
|
||||
///////////////
|
||||
@@ -240,9 +240,9 @@
|
||||
match = matches[++k];
|
||||
q = props[p];
|
||||
// check if given property is actually array
|
||||
if (typeof q === OBJ_TYPE && q.length > 0) {
|
||||
if (typeof q === TYPEOF.OBJECT && q.length > 0) {
|
||||
if (q.length === 2) {
|
||||
if (typeof q[1] == FUNC_TYPE) {
|
||||
if (typeof q[1] == TYPEOF.FUNCTION) {
|
||||
// assign modified match
|
||||
this[q[0]] = q[1].call(this, match);
|
||||
} else {
|
||||
@@ -251,7 +251,7 @@
|
||||
}
|
||||
} else if (q.length >= 3) {
|
||||
// Check whether q[1] FUNCTION or REGEX
|
||||
if (typeof q[1] === FUNC_TYPE && !(q[1].exec && q[1].test)) {
|
||||
if (typeof q[1] === TYPEOF.FUNCTION && !(q[1].exec && q[1].test)) {
|
||||
if (q.length > 3) {
|
||||
this[q[0]] = match ? q[1].apply(this, q.slice(2)) : undefined;
|
||||
} else {
|
||||
@@ -283,7 +283,7 @@
|
||||
|
||||
for (var i in map) {
|
||||
// check if current value is array
|
||||
if (typeof map[i] === OBJ_TYPE && map[i].length > 0) {
|
||||
if (typeof map[i] === TYPEOF.OBJECT && map[i].length > 0) {
|
||||
for (var j = 0; j < map[i].length; j++) {
|
||||
if (has(map[i][j], str)) {
|
||||
return (i === UNKNOWN) ? undefined : i;
|
||||
@@ -377,10 +377,11 @@
|
||||
/(avant|iemobile|slim(?:browser|boat|jet))[\/ ]?([\d\.]*)/i, // Avant/IEMobile/SlimBrowser/SlimBoat/Slimjet
|
||||
/(?:ms|\()(ie) ([\w\.]+)/i, // Internet Explorer
|
||||
|
||||
// Blink/Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon/LG Browser/Otter/qutebrowser/Dooble
|
||||
/(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio|(?=comodo_)?dragon|otter|dooble|(?:lg |qute)browser)\/([-\w\.]+)/i,
|
||||
// Blink/Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon/LG Browser/Otter/qutebrowser/Dooble/Palemoon
|
||||
/(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio|(?=comodo_)?dragon|otter|dooble|(?:lg |qute)browser|palemoon)\/([-\w\.]+)/i,
|
||||
// Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio/Dragon
|
||||
/(heytap|ovi|115|surf)browser\/([\d\.]+)/i, // HeyTap/Ovi/115/Surf
|
||||
/(heytap|ovi|115|surf|qwant)browser\/([\d\.]+)/i, // HeyTap/Ovi/115/Surf
|
||||
/(qwant)(?:ios|mobile)\/([\d\.]+)/i, // Qwant
|
||||
/(ecosia|weibo)(?:__| \w+@)([\d\.]+)/i // Ecosia/Weibo
|
||||
], [NAME, VERSION], [
|
||||
/quark(?:pc)?\/([-\w\.]+)/i // Quark
|
||||
@@ -449,6 +450,7 @@
|
||||
/\b(line)\/([\w\.]+)\/iab/i, // Line App for Android
|
||||
/(alipay)client\/([\w\.]+)/i, // Alipay
|
||||
/(twitter)(?:and| f.+e\/([\w\.]+))/i, // Twitter
|
||||
/(bing)(?:web|sapphire)\/([\w\.]+)/i, // Bing
|
||||
/(instagram|snapchat|klarna)[\/ ]([-\w\.]+)/i // Instagram/Snapchat/Klarna
|
||||
], [NAME, VERSION, [TYPE, INAPP]], [
|
||||
/\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS
|
||||
@@ -457,6 +459,8 @@
|
||||
], [VERSION, [NAME, 'TikTok'], [TYPE, INAPP]], [
|
||||
/\[(linkedin)app\]/i // LinkedIn App for iOS & Android
|
||||
], [NAME, [TYPE, INAPP]], [
|
||||
/(zalo(?:app)?)[\/\sa-z]*([\w\.-]+)/i // Zalo
|
||||
], [[NAME, /(.+)/, 'Zalo'], VERSION, [TYPE, INAPP]], [
|
||||
|
||||
/(chromium)[\/ ]([-\w\.]+)/i // Chromium
|
||||
], [NAME, VERSION], [
|
||||
@@ -504,10 +508,10 @@
|
||||
/(swiftfox)/i, // Swiftfox
|
||||
/(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror)[\/ ]?([\w\.\+]+)/i,
|
||||
// IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror
|
||||
/(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\/([-\w\.]+)$/i,
|
||||
/(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|basilisk|waterfox)\/([-\w\.]+)$/i,
|
||||
// Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix
|
||||
/(firefox)\/([\w\.]+)/i, // Other Firefox-based
|
||||
/(mozilla)\/([\w\.]+) .+rv\:.+gecko\/\d+/i, // Mozilla
|
||||
/(mozilla)\/([\w\.]+(?= .+rv\:.+gecko\/\d+)|[0-4][\w\.]+(?!.+compatible))/i, // Mozilla
|
||||
|
||||
// Other
|
||||
/(amaya|dillo|doris|icab|ladybird|lynx|mosaic|netsurf|obigo|polaris|w3m|(?:go|ice|up)[\. ]?browser)[-\/ ]?v?([\w\.]+)/i,
|
||||
@@ -538,15 +542,17 @@
|
||||
/( (ce|mobile); ppc;|\/[\w\.]+arm\b)/i
|
||||
], [[ARCHITECTURE, 'arm']], [
|
||||
|
||||
/((ppc|powerpc)(64)?)( mac|;|\))/i // PowerPC
|
||||
], [[ARCHITECTURE, /ower/, EMPTY, lowerize]], [
|
||||
|
||||
/ sun4\w[;\)]/i // SPARC
|
||||
], [[ARCHITECTURE, 'sparc']], [
|
||||
|
||||
/\b(avr32|ia64(?=;)|68k(?=\))|\barm(?=v([1-7]|[5-7]1)l?|;|eabi)|(irix|mips|sparc)(64)?\b|pa-risc)/i
|
||||
// IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC
|
||||
], [[ARCHITECTURE, lowerize]]
|
||||
/\b(avr32|ia64(?=;)|68k(?=\))|\barm(?=v([1-7]|[5-7]1)l?|;|eabi)|(irix|mips|sparc)(64)?\b|pa-risc)/i,
|
||||
/((ppc|powerpc)(64)?)( mac|;|\))/i, // PowerPC
|
||||
/(?:osf1|[freopnt]{3,4}bsd) (alpha)/i // Alpha
|
||||
], [[ARCHITECTURE, /ower/, EMPTY, lowerize]], [
|
||||
/mc680.0/i
|
||||
], [[ARCHITECTURE, '68k']], [
|
||||
/winnt.+\[axp/i
|
||||
], [[ARCHITECTURE, 'alpha']]
|
||||
],
|
||||
|
||||
device : [[
|
||||
@@ -564,11 +570,10 @@
|
||||
], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [
|
||||
|
||||
// Apple
|
||||
/(?:\/|\()(ip(?:hone|od)[\w, ]*)(?:\/|;)/i // iPod/iPhone
|
||||
/(?:\/|\()(ip(?:hone|od)[\w, ]*)[\/\);]/i // iPod/iPhone
|
||||
], [MODEL, [VENDOR, APPLE], [TYPE, MOBILE]], [
|
||||
/\((ipad);[-\w\),; ]+apple/i, // iPad
|
||||
/applecoremedia\/[\w\.]+ \((ipad)/i,
|
||||
/\b(ipad)\d\d?,\d\d?[;\]].+ios/i
|
||||
/\b(?:ios|apple\w+)\/.+[\(\/](ipad)/i, // iPad
|
||||
/\b(ipad)[\d,]*[;\] ].+(mac |i(pad)?)os/i
|
||||
], [MODEL, [VENDOR, APPLE], [TYPE, TABLET]], [
|
||||
/(macintosh);/i
|
||||
], [MODEL, [VENDOR, APPLE]], [
|
||||
@@ -586,13 +591,13 @@
|
||||
// Huawei
|
||||
/\b((?:ag[rs][2356]?k?|bah[234]?|bg[2o]|bt[kv]|cmr|cpn|db[ry]2?|jdn2|got|kob2?k?|mon|pce|scm|sht?|[tw]gr|vrd)-[ad]?[lw][0125][09]b?|605hw|bg2-u03|(?:gem|fdr|m2|ple|t1)-[7a]0[1-4][lu]|t1-a2[13][lw]|mediapad[\w\. ]*(?= bui|\)))\b(?!.+d\/s)/i
|
||||
], [MODEL, [VENDOR, HUAWEI], [TYPE, TABLET]], [
|
||||
/(?:huawei)([-\w ]+)[;\)]/i,
|
||||
/\b(nexus 6p|\w{2,4}e?-[atu]?[ln][\dx][012359c][adn]?)\b(?!.+d\/s)/i
|
||||
/(?:huawei) ?([-\w ]+)[;\)]/i,
|
||||
/\b(nexus 6p|\w{2,4}e?-[atu]?[ln][\dx][\dc][adnt]?)\b(?!.+d\/s)/i
|
||||
], [MODEL, [VENDOR, HUAWEI], [TYPE, MOBILE]], [
|
||||
|
||||
// Xiaomi
|
||||
/oid[^\)]+; (2[\dbc]{4}(182|283|rp\w{2})[cgl]|m2105k81a?c)(?: bui|\))/i,
|
||||
/\b((?:red)?mi[-_ ]?pad[\w- ]*)(?: bui|\))/i // Mi Pad tablets
|
||||
/\b(?:xiao)?((?:red)?mi[-_ ]?pad[\w- ]*)(?: bui|\))/i // Mi Pad tablets
|
||||
],[[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, TABLET]], [
|
||||
|
||||
/\b(poco[\w ]+|m2\d{3}j\d\d[a-z]{2})(?: bui|\))/i, // Xiaomi POCO
|
||||
@@ -600,7 +605,7 @@
|
||||
/\b(hm[-_ ]?note?[_ ]?(?:\d\w)?) bui/i, // Xiaomi Hongmi
|
||||
/\b(redmi[\-_ ]?(?:note|k)?[\w_ ]+)(?: bui|\))/i, // Xiaomi Redmi
|
||||
/oid[^\)]+; (m?[12][0-389][01]\w{3,6}[c-y])( bui|; wv|\))/i, // Xiaomi Redmi 'numeric' models
|
||||
/\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note lte|max|cc)?[_ ]?(?:\d?\w?)[_ ]?(?:plus|se|lite|pro)?)(?: bui|\))/i, // Xiaomi Mi
|
||||
/\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note|max|cc)?[_ ]?(?:\d{0,2}\w?)[_ ]?(?:plus|se|lite|pro)?( 5g|lte)?)(?: bui|\))/i, // Xiaomi Mi
|
||||
/ ([\w ]+) miui\/v?\d/i
|
||||
], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [
|
||||
|
||||
@@ -656,7 +661,7 @@
|
||||
/(nokia) (t[12][01])/i
|
||||
], [VENDOR, MODEL, [TYPE, TABLET]], [
|
||||
/(?:maemo|nokia).*(n900|lumia \d+|rm-\d+)/i,
|
||||
/nokia[-_ ]?(([-\w\. ]*))/i
|
||||
/nokia[-_ ]?(([-\w\. ]*?))( bui|\)|;|\/)/i
|
||||
], [[MODEL, /_/g, ' '], [TYPE, MOBILE], [VENDOR, 'Nokia']], [
|
||||
|
||||
// Google
|
||||
@@ -687,7 +692,7 @@
|
||||
/(playbook);[-\w\),; ]+(rim)/i // BlackBerry PlayBook
|
||||
], [MODEL, VENDOR, [TYPE, TABLET]], [
|
||||
/\b((?:bb[a-f]|st[hv])100-\d)/i,
|
||||
/\(bb10; (\w+)/i // BlackBerry 10
|
||||
/(?:blackberry|\(bb10;) (\w+)/i
|
||||
], [MODEL, [VENDOR, BLACKBERRY], [TYPE, MOBILE]], [
|
||||
|
||||
// Asus
|
||||
@@ -767,10 +772,13 @@
|
||||
|
||||
/(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus(?! zenw)|dell|jolla|meizu|motorola|polytron|tecno|micromax|advan)[-_ ]?([-\w]*)/i,
|
||||
// BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron/Tecno/Micromax/Advan
|
||||
/; (blu|hmd|imo|infinix|lava|oneplus|tcl)[_ ]([\w\+ ]+?)(?: bui|\)|; r)/i, // BLU/HMD/IMO/Infinix/Lava/OnePlus/TCL
|
||||
// BLU/HMD/IMO/Infinix/Lava/OnePlus/TCL/Wiko
|
||||
/; (blu|hmd|imo|infinix|lava|oneplus|tcl|wiko)[_ ]([\w\+ ]+?)(?: bui|\)|; r)/i,
|
||||
/(hp) ([\w ]+\w)/i, // HP iPAQ
|
||||
/(microsoft); (lumia[\w ]+)/i, // Microsoft Lumia
|
||||
/(oppo) ?([\w ]+) bui/i // OPPO
|
||||
/(oppo) ?([\w ]+) bui/i, // OPPO
|
||||
/(hisense) ([ehv][\w ]+)\)/i, // Hisense
|
||||
/droid[^;]+; (philips)[_ ]([sv-x][\d]{3,4}[xz]?)/i // Philips
|
||||
], [VENDOR, MODEL, [TYPE, MOBILE]], [
|
||||
|
||||
/(kobo)\s(ereader|touch)/i, // Kobo
|
||||
@@ -797,6 +805,7 @@
|
||||
// SMARTTVS
|
||||
///////////////////
|
||||
|
||||
/(philips)[\w ]+tv/i, // Philips
|
||||
/smart-tv.+(samsung)/i // Samsung
|
||||
], [VENDOR, [TYPE, SMARTTV]], [
|
||||
/hbbtv.+maple;(\d+)/i
|
||||
@@ -834,11 +843,6 @@
|
||||
/\b(roku)[\dx]*[\)\/]((?:dvp-)?[\d\.]*)/i, // Roku
|
||||
/hbbtv\/\d+\.\d+\.\d+ +\([\w\+ ]*; *([\w\d][^;]*);([^;]*)/i // HbbTV devices
|
||||
], [[VENDOR, /.+\/(\w+)/, '$1', strMapper, {'LG':'lge'}], [MODEL, trim], [TYPE, SMARTTV]], [
|
||||
// SmartTV from Unidentified Vendors
|
||||
/droid.+; ([\w- ]+) (?:android tv|smart[- ]?tv)/i
|
||||
], [MODEL, [TYPE, SMARTTV]], [
|
||||
/\b(android tv|smart[- ]?tv|opera tv|tv; rv:|large screen[\w ]+safari)\b/i
|
||||
], [[TYPE, SMARTTV]], [
|
||||
|
||||
///////////////////
|
||||
// CONSOLES
|
||||
@@ -885,7 +889,7 @@
|
||||
|
||||
/droid.+; (glass) \d/i // Google Glass
|
||||
], [MODEL, [VENDOR, GOOGLE], [TYPE, XR]], [
|
||||
/(pico) (4|neo3(?: link|pro)?)/i // Pico
|
||||
/(pico) ([\w ]+) os\d/i // Pico
|
||||
], [VENDOR, MODEL, [TYPE, XR]], [
|
||||
/(quest( \d| pro)?s?).+vr/i // Meta Quest
|
||||
], [MODEL, [VENDOR, FACEBOOK], [TYPE, XR]], [
|
||||
@@ -909,7 +913,11 @@
|
||||
// MIXED (GENERIC)
|
||||
///////////////////
|
||||
|
||||
/droid .+?; ([^;]+?)(?: bui|; wv\)|\) applew).+?(mobile|vr|\d) safari/i
|
||||
/droid.+; ([\w- ]+) (4k|android|smart|google)[- ]?tv/i // Unidentifiable SmartTV
|
||||
], [MODEL, [TYPE, SMARTTV]], [
|
||||
/\b((4k|android|smart|opera)[- ]?tv|tv; rv:|large screen[\w ]+safari)\b/i
|
||||
], [[TYPE, SMARTTV]], [
|
||||
/droid .+?; ([^;]+?)(?: bui|; wv\)|\) applew|; hmsc).+?(mobile|vr|\d) safari/i
|
||||
], [MODEL, [TYPE, strMapper, { 'mobile' : 'Mobile', 'xr' : 'VR', '*' : TABLET }]], [
|
||||
/\b((tablet|tab)[;\/]|focus\/\d(?!.+mobile))/i // Unidentifiable Tablet
|
||||
], [[TYPE, TABLET]], [
|
||||
@@ -962,7 +970,7 @@
|
||||
|
||||
// iOS/macOS
|
||||
/[adehimnop]{4,7}\b(?:.*os ([\w]+) like mac|; opera)/i, // iOS
|
||||
/(?:ios;fbsv\/|iphone.+ios[\/ ])([\d\.]+)/i,
|
||||
/(?:ios;fbsv|ios(?=.+ip(?:ad|hone))|ip(?:ad|hone)(?: |.+i(?:pad)?)os)[\/ ]([\w\.]+)/i,
|
||||
/cfnetwork\/.+darwin/i
|
||||
], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [
|
||||
/(mac os x) ?([\w\. ]*)/i,
|
||||
@@ -1047,27 +1055,27 @@
|
||||
var defaultProps = (function () {
|
||||
var props = { init : {}, isIgnore : {}, isIgnoreRgx : {}, toString : {}};
|
||||
setProps.call(props.init, [
|
||||
[UA_BROWSER, [NAME, VERSION, MAJOR, TYPE]],
|
||||
[UA_CPU, [ARCHITECTURE]],
|
||||
[UA_DEVICE, [TYPE, MODEL, VENDOR]],
|
||||
[UA_ENGINE, [NAME, VERSION]],
|
||||
[UA_OS, [NAME, VERSION]]
|
||||
[BROWSER, [NAME, VERSION, MAJOR, TYPE]],
|
||||
[CPU, [ARCHITECTURE]],
|
||||
[DEVICE, [TYPE, MODEL, VENDOR]],
|
||||
[ENGINE, [NAME, VERSION]],
|
||||
[OS, [NAME, VERSION]]
|
||||
]);
|
||||
setProps.call(props.isIgnore, [
|
||||
[UA_BROWSER, [VERSION, MAJOR]],
|
||||
[UA_ENGINE, [VERSION]],
|
||||
[UA_OS, [VERSION]]
|
||||
[BROWSER, [VERSION, MAJOR]],
|
||||
[ENGINE, [VERSION]],
|
||||
[OS, [VERSION]]
|
||||
]);
|
||||
setProps.call(props.isIgnoreRgx, [
|
||||
[UA_BROWSER, / ?browser$/i],
|
||||
[UA_OS, / ?os$/i]
|
||||
[BROWSER, / ?browser$/i],
|
||||
[OS, / ?os$/i]
|
||||
]);
|
||||
setProps.call(props.toString, [
|
||||
[UA_BROWSER, [NAME, VERSION]],
|
||||
[UA_CPU, [ARCHITECTURE]],
|
||||
[UA_DEVICE, [VENDOR, MODEL]],
|
||||
[UA_ENGINE, [NAME, VERSION]],
|
||||
[UA_OS, [NAME, VERSION]]
|
||||
[BROWSER, [NAME, VERSION]],
|
||||
[CPU, [ARCHITECTURE]],
|
||||
[DEVICE, [VENDOR, MODEL]],
|
||||
[ENGINE, [NAME, VERSION]],
|
||||
[OS, [NAME, VERSION]]
|
||||
]);
|
||||
return props;
|
||||
})();
|
||||
@@ -1111,14 +1119,14 @@
|
||||
return item.detectFeature().get();
|
||||
};
|
||||
|
||||
if (itemType != UA_RESULT) {
|
||||
if (itemType != RESULT) {
|
||||
IData.prototype.is = function (strToCheck) {
|
||||
var is = false;
|
||||
for (var i in this) {
|
||||
if (this.hasOwnProperty(i) && !has(is_ignoreProps, i) && lowerize(is_ignoreRgx ? strip(is_ignoreRgx, this[i]) : this[i]) == lowerize(is_ignoreRgx ? strip(is_ignoreRgx, strToCheck) : strToCheck)) {
|
||||
is = true;
|
||||
if (strToCheck != UNDEF_TYPE) break;
|
||||
} else if (strToCheck == UNDEF_TYPE && is) {
|
||||
if (strToCheck != TYPEOF.UNDEFINED) break;
|
||||
} else if (strToCheck == TYPEOF.UNDEFINED && is) {
|
||||
is = !is;
|
||||
break;
|
||||
}
|
||||
@@ -1128,11 +1136,11 @@
|
||||
IData.prototype.toString = function () {
|
||||
var str = EMPTY;
|
||||
for (var i in toString_props) {
|
||||
if (typeof(this[toString_props[i]]) !== UNDEF_TYPE) {
|
||||
if (typeof(this[toString_props[i]]) !== TYPEOF.UNDEFINED) {
|
||||
str += (str ? ' ' : EMPTY) + this[toString_props[i]];
|
||||
}
|
||||
}
|
||||
return str || UNDEF_TYPE;
|
||||
return str || TYPEOF.UNDEFINED;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1168,19 +1176,19 @@
|
||||
setProps.call(this, CH_ALL_VALUES);
|
||||
if (isHttpUACH) {
|
||||
setProps.call(this, [
|
||||
[BRANDS, itemListToArray(uach[CH_HEADER])],
|
||||
[FULLVERLIST, itemListToArray(uach[CH_HEADER_FULL_VER_LIST])],
|
||||
[MOBILE, /\?1/.test(uach[CH_HEADER_MOBILE])],
|
||||
[MODEL, stripQuotes(uach[CH_HEADER_MODEL])],
|
||||
[PLATFORM, stripQuotes(uach[CH_HEADER_PLATFORM])],
|
||||
[PLATFORMVER, stripQuotes(uach[CH_HEADER_PLATFORM_VER])],
|
||||
[ARCHITECTURE, stripQuotes(uach[CH_HEADER_ARCH])],
|
||||
[FORMFACTORS, itemListToArray(uach[CH_HEADER_FORM_FACTORS])],
|
||||
[BITNESS, stripQuotes(uach[CH_HEADER_BITNESS])]
|
||||
[BRANDS, itemListToArray(uach[CH])],
|
||||
[FULLVERLIST, itemListToArray(uach[CH_FULL_VER_LIST])],
|
||||
[MOBILE, /\?1/.test(uach[CH_MOBILE])],
|
||||
[MODEL, stripQuotes(uach[CH_MODEL])],
|
||||
[PLATFORM, stripQuotes(uach[CH_PLATFORM])],
|
||||
[PLATFORMVER, stripQuotes(uach[CH_PLATFORM_VER])],
|
||||
[ARCHITECTURE, stripQuotes(uach[CH_ARCH])],
|
||||
[FORMFACTORS, itemListToArray(uach[CH_FORM_FACTORS])],
|
||||
[BITNESS, stripQuotes(uach[CH_BITNESS])]
|
||||
]);
|
||||
} else {
|
||||
for (var prop in uach) {
|
||||
if(this.hasOwnProperty(prop) && typeof uach[prop] !== UNDEF_TYPE) this[prop] = uach[prop];
|
||||
if(this.hasOwnProperty(prop) && typeof uach[prop] !== TYPEOF.UNDEFINED) this[prop] = uach[prop];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1205,30 +1213,30 @@
|
||||
this.detectFeature = function () {
|
||||
if (NAVIGATOR && NAVIGATOR.userAgent == this.ua) {
|
||||
switch (this.itemType) {
|
||||
case UA_BROWSER:
|
||||
case BROWSER:
|
||||
// Brave-specific detection
|
||||
if (NAVIGATOR.brave && typeof NAVIGATOR.brave.isBrave == FUNC_TYPE) {
|
||||
if (NAVIGATOR.brave && typeof NAVIGATOR.brave.isBrave == TYPEOF.FUNCTION) {
|
||||
this.set(NAME, 'Brave');
|
||||
}
|
||||
break;
|
||||
case UA_DEVICE:
|
||||
case DEVICE:
|
||||
// Chrome-specific detection: check for 'mobile' value of navigator.userAgentData
|
||||
if (!this.get(TYPE) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[MOBILE]) {
|
||||
this.set(TYPE, MOBILE);
|
||||
}
|
||||
// iPadOS-specific detection: identified as Mac, but has some iOS-only properties
|
||||
if (this.get(MODEL) == 'Macintosh' && NAVIGATOR && typeof NAVIGATOR.standalone !== UNDEF_TYPE && NAVIGATOR.maxTouchPoints && NAVIGATOR.maxTouchPoints > 2) {
|
||||
if (this.get(MODEL) == 'Macintosh' && NAVIGATOR && typeof NAVIGATOR.standalone !== TYPEOF.UNDEFINED && NAVIGATOR.maxTouchPoints && NAVIGATOR.maxTouchPoints > 2) {
|
||||
this.set(MODEL, 'iPad')
|
||||
.set(TYPE, TABLET);
|
||||
}
|
||||
break;
|
||||
case UA_OS:
|
||||
case OS:
|
||||
// Chrome-specific detection: check for 'platform' value of navigator.userAgentData
|
||||
if (!this.get(NAME) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[PLATFORM]) {
|
||||
this.set(NAME, NAVIGATOR_UADATA[PLATFORM]);
|
||||
}
|
||||
break;
|
||||
case UA_RESULT:
|
||||
case RESULT:
|
||||
var data = this.data;
|
||||
var detect = function (itemType) {
|
||||
return data[itemType]
|
||||
@@ -1236,22 +1244,33 @@
|
||||
.detectFeature()
|
||||
.get();
|
||||
};
|
||||
this.set(UA_BROWSER, detect(UA_BROWSER))
|
||||
.set(UA_CPU, detect(UA_CPU))
|
||||
.set(UA_DEVICE, detect(UA_DEVICE))
|
||||
.set(UA_ENGINE, detect(UA_ENGINE))
|
||||
.set(UA_OS, detect(UA_OS));
|
||||
this.set(BROWSER, detect(BROWSER))
|
||||
.set(CPU, detect(CPU))
|
||||
.set(DEVICE, detect(DEVICE))
|
||||
.set(ENGINE, detect(ENGINE))
|
||||
.set(OS, detect(OS));
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
this.parseUA = function () {
|
||||
if (this.itemType != UA_RESULT) {
|
||||
if (this.itemType != RESULT) {
|
||||
rgxMapper.call(this.data, this.ua, this.rgxMap);
|
||||
}
|
||||
if (this.itemType == UA_BROWSER) {
|
||||
this.set(MAJOR, majorize(this.get(VERSION)));
|
||||
switch (this.itemType) {
|
||||
case BROWSER:
|
||||
this.set(MAJOR, majorize(this.get(VERSION)));
|
||||
break;
|
||||
case OS:
|
||||
if (this.get(NAME) == 'iOS' && this.get(VERSION) == '18.6') {
|
||||
// Based on the assumption that iOS version is tightly coupled with Safari version
|
||||
var realVersion = /\) Version\/([\d\.]+)/.exec(this.ua); // Get Safari version
|
||||
if (realVersion && parseInt(realVersion[1].substring(0,2), 10) >= 26) {
|
||||
this.set(VERSION, realVersion[1]); // Set as iOS version
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return this;
|
||||
};
|
||||
@@ -1261,14 +1280,14 @@
|
||||
rgxMap = this.rgxMap;
|
||||
|
||||
switch (this.itemType) {
|
||||
case UA_BROWSER:
|
||||
case UA_ENGINE:
|
||||
case BROWSER:
|
||||
case ENGINE:
|
||||
var brands = uaCH[FULLVERLIST] || uaCH[BRANDS], prevName;
|
||||
if (brands) {
|
||||
for (var i in brands) {
|
||||
for (var i=0; i<brands.length; i++) {
|
||||
var brandName = brands[i].brand || brands[i],
|
||||
brandVersion = brands[i].version;
|
||||
if (this.itemType == UA_BROWSER &&
|
||||
if (this.itemType == BROWSER &&
|
||||
!/not.a.brand/i.test(brandName) &&
|
||||
(!prevName ||
|
||||
(/Chrom/.test(prevName) && brandName != CHROMIUM) ||
|
||||
@@ -1283,20 +1302,20 @@
|
||||
}
|
||||
prevName = brandName;
|
||||
}
|
||||
if (this.itemType == UA_ENGINE && brandName == CHROMIUM) {
|
||||
if (this.itemType == ENGINE && brandName == CHROMIUM) {
|
||||
this.set(VERSION, brandVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case UA_CPU:
|
||||
case CPU:
|
||||
var archName = uaCH[ARCHITECTURE];
|
||||
if (archName) {
|
||||
if (archName && uaCH[BITNESS] == '64') archName += '64';
|
||||
rgxMapper.call(this.data, archName + ';', rgxMap);
|
||||
}
|
||||
break;
|
||||
case UA_DEVICE:
|
||||
case DEVICE:
|
||||
if (uaCH[MOBILE]) {
|
||||
this.set(TYPE, MOBILE);
|
||||
}
|
||||
@@ -1326,7 +1345,7 @@
|
||||
this.set(TYPE, ff);
|
||||
}
|
||||
break;
|
||||
case UA_OS:
|
||||
case OS:
|
||||
var osName = uaCH[PLATFORM];
|
||||
if(osName) {
|
||||
var osVersion = uaCH[PLATFORMVER];
|
||||
@@ -1340,7 +1359,7 @@
|
||||
.set(VERSION, undefined);
|
||||
}
|
||||
break;
|
||||
case UA_RESULT:
|
||||
case RESULT:
|
||||
var data = this.data;
|
||||
var parse = function (itemType) {
|
||||
return data[itemType]
|
||||
@@ -1349,11 +1368,11 @@
|
||||
.parseCH()
|
||||
.get();
|
||||
};
|
||||
this.set(UA_BROWSER, parse(UA_BROWSER))
|
||||
.set(UA_CPU, parse(UA_CPU))
|
||||
.set(UA_DEVICE, parse(UA_DEVICE))
|
||||
.set(UA_ENGINE, parse(UA_ENGINE))
|
||||
.set(UA_OS, parse(UA_OS));
|
||||
this.set(BROWSER, parse(BROWSER))
|
||||
.set(CPU, parse(CPU))
|
||||
.set(DEVICE, parse(DEVICE))
|
||||
.set(ENGINE, parse(ENGINE))
|
||||
.set(OS, parse(OS));
|
||||
}
|
||||
return this;
|
||||
};
|
||||
@@ -1371,9 +1390,9 @@
|
||||
|
||||
function UAParser (ua, extensions, headers) {
|
||||
|
||||
if (typeof ua === OBJ_TYPE) {
|
||||
if (typeof ua === TYPEOF.OBJECT) {
|
||||
if (isExtensions(ua, true)) {
|
||||
if (typeof extensions === OBJ_TYPE) {
|
||||
if (typeof extensions === TYPEOF.OBJECT) {
|
||||
headers = extensions; // case UAParser(extensions, headers)
|
||||
}
|
||||
extensions = ua; // case UAParser(extensions)
|
||||
@@ -1382,23 +1401,34 @@
|
||||
extensions = undefined;
|
||||
}
|
||||
ua = undefined;
|
||||
} else if (typeof ua === STR_TYPE && !isExtensions(extensions, true)) {
|
||||
} else if (typeof ua === TYPEOF.STRING && !isExtensions(extensions, true)) {
|
||||
headers = extensions; // case UAParser(ua, headers)
|
||||
extensions = undefined;
|
||||
}
|
||||
|
||||
// Convert Headers object into a plain object
|
||||
if (headers && typeof headers.append === FUNC_TYPE) {
|
||||
var kv = {};
|
||||
headers.forEach(function (v, k) { kv[k] = v; });
|
||||
headers = kv;
|
||||
if (headers) {
|
||||
if (typeof headers.append === TYPEOF.FUNCTION) {
|
||||
// Convert Headers object into a plain object
|
||||
var kv = {};
|
||||
headers.forEach(function (v, k) { kv[String(k).toLowerCase()] = v; });
|
||||
headers = kv;
|
||||
} else {
|
||||
// Normalize headers field name into lowercase
|
||||
var normalized = {};
|
||||
for (var header in headers) {
|
||||
if (headers.hasOwnProperty(header)) {
|
||||
normalized[String(header).toLowerCase()] = headers[header];
|
||||
}
|
||||
}
|
||||
headers = normalized;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(this instanceof UAParser)) {
|
||||
return new UAParser(ua, extensions, headers).getResult();
|
||||
}
|
||||
|
||||
var userAgent = typeof ua === STR_TYPE ? ua : // Passed user-agent string
|
||||
var userAgent = typeof ua === TYPEOF.STRING ? ua : // Passed user-agent string
|
||||
(headers && headers[USER_AGENT] ? headers[USER_AGENT] : // User-Agent from passed headers
|
||||
((NAVIGATOR && NAVIGATOR.userAgent) ? NAVIGATOR.userAgent : // navigator.userAgent
|
||||
EMPTY)), // empty string
|
||||
@@ -1409,15 +1439,15 @@
|
||||
defaultRegexes,
|
||||
|
||||
createItemFunc = function (itemType) {
|
||||
if (itemType == UA_RESULT) {
|
||||
if (itemType == RESULT) {
|
||||
return function () {
|
||||
return new UAItem(itemType, userAgent, regexMap, httpUACH)
|
||||
.set('ua', userAgent)
|
||||
.set(UA_BROWSER, this.getBrowser())
|
||||
.set(UA_CPU, this.getCPU())
|
||||
.set(UA_DEVICE, this.getDevice())
|
||||
.set(UA_ENGINE, this.getEngine())
|
||||
.set(UA_OS, this.getOS())
|
||||
.set(BROWSER, this.getBrowser())
|
||||
.set(CPU, this.getCPU())
|
||||
.set(DEVICE, this.getDevice())
|
||||
.set(ENGINE, this.getEngine())
|
||||
.set(OS, this.getOS())
|
||||
.get();
|
||||
};
|
||||
} else {
|
||||
@@ -1431,16 +1461,15 @@
|
||||
|
||||
// public methods
|
||||
setProps.call(this, [
|
||||
['getBrowser', createItemFunc(UA_BROWSER)],
|
||||
['getCPU', createItemFunc(UA_CPU)],
|
||||
['getDevice', createItemFunc(UA_DEVICE)],
|
||||
['getEngine', createItemFunc(UA_ENGINE)],
|
||||
['getOS', createItemFunc(UA_OS)],
|
||||
['getResult', createItemFunc(UA_RESULT)],
|
||||
['getBrowser', createItemFunc(BROWSER)],
|
||||
['getCPU', createItemFunc(CPU)],
|
||||
['getDevice', createItemFunc(DEVICE)],
|
||||
['getEngine', createItemFunc(ENGINE)],
|
||||
['getOS', createItemFunc(OS)],
|
||||
['getResult', createItemFunc(RESULT)],
|
||||
['getUA', function () { return userAgent; }],
|
||||
['setUA', function (ua) {
|
||||
if (isString(ua))
|
||||
userAgent = ua.length > UA_MAX_LENGTH ? trim(ua, UA_MAX_LENGTH) : ua;
|
||||
if (isString(ua)) userAgent = trim(ua, UA_MAX_LENGTH);
|
||||
return this;
|
||||
}]
|
||||
])
|
||||
|
||||
242
test/data/ua-ch/headers.js
Normal file
242
test/data/ua-ch/headers.js
Normal file
@@ -0,0 +1,242 @@
|
||||
const UACHTests = [
|
||||
{
|
||||
desc: 'Avast Secure Browser',
|
||||
headers : {
|
||||
'sec-ch-ua': '"Avast Secure Browser";v="131", "Chromium";v="131", "Not_A Brand";v="24"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Avast Secure Browser',
|
||||
version : '131',
|
||||
major : '131',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: 'Brave',
|
||||
headers : {
|
||||
'sec-ch-ua': '"Not A(Brand";v="8", "Chromium";v="132", "Brave";v="132"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Brave',
|
||||
version : '132',
|
||||
major : '132',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: 'Chrome',
|
||||
headers : {
|
||||
'sec-ch-ua': '"Google Chrome";v="111", "Not(A:Brand";v="8", "Chromium";v="111"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Chrome',
|
||||
version : '111',
|
||||
major : '111',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: 'Chrome Headless',
|
||||
headers : {
|
||||
'sec-ch-ua': '"Chromium";v="124", "HeadlessChrome";v="124", "Not-A.Brand";v="99"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Chrome Headless',
|
||||
version : '124',
|
||||
major : '124',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: 'Chrome WebView',
|
||||
headers : {
|
||||
'sec-ch-ua': '"Android WebView";v="123", "Not:A-Brand";v="8", "Chromium";v="123"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Chrome WebView',
|
||||
version : '123',
|
||||
major : '123',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: 'DuckDuckGo',
|
||||
headers : {
|
||||
'sec-ch-ua': '"DuckDuckGo";v="131", "Chromium";v="131", "Not_A Brand";v="24"'
|
||||
},
|
||||
expect : {
|
||||
browser : {
|
||||
name : 'DuckDuckGo',
|
||||
version : '131',
|
||||
major : '131',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: 'Edge',
|
||||
headers : {
|
||||
'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Edge',
|
||||
version : '120',
|
||||
major : '120',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: 'Edge WebView2',
|
||||
headers : {
|
||||
'sec-ch-ua': '" Not;A Brand";v="99", "Microsoft Edge";v="103", "Chromium";v="103", "Microsoft Edge WebView2";v="104"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Edge WebView2',
|
||||
version : '104',
|
||||
major : '104',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: 'Huawei Browser',
|
||||
headers : {
|
||||
'sec-ch-ua': '"Not.A/Brand";v="8", "Chromium";v="114", "HuaweiBrowser";v="114"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Huawei Browser',
|
||||
version : '114',
|
||||
major : '114',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: 'MIUI Browser',
|
||||
headers : {
|
||||
'sec-ch-ua': '"Miui Browser";v="123", "Not:A-Brand";v="8", "Chromium";v="123"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'MIUI Browser',
|
||||
version : '123',
|
||||
major : '123',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: 'Oculus Browser',
|
||||
headers : {
|
||||
'sec-ch-ua': '"Chromium";v="130", "Oculus Browser";v="36", "Not?A_Brand";v="99"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Oculus Browser',
|
||||
version : '36',
|
||||
major : '36',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: 'Opera',
|
||||
headers : {
|
||||
'sec-ch-ua': '"Opera";v="116", "Chromium";v="131", "Not_A Brand";v="24"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Opera',
|
||||
version : '116',
|
||||
major : '116',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: 'Opera GX',
|
||||
headers : {
|
||||
'sec-ch-ua': '"Chromium";v="128", "Not;A=Brand";v="24", "Opera GX";v="114"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Opera GX',
|
||||
version : '114',
|
||||
major : '114',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: 'Opera Mobi',
|
||||
headers : {
|
||||
'sec-ch-ua': '"OperaMobile";v="86", ";Not A Brand";v="99", "Opera";v="115", "Chromium";v="130"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Opera Mobi',
|
||||
version : '86',
|
||||
major : '86',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: 'Opera Mobi',
|
||||
headers : {
|
||||
'sec-ch-ua': '"Chromium";v="132", "OperaMobile";v="87", "Opera";v="117", " Not A;Brand";v="99"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Opera Mobi',
|
||||
version : '87',
|
||||
major : '87',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: 'Samsung Internet',
|
||||
headers : {
|
||||
'sec-ch-ua': '"Chromium";v="125", "Not.A/Brand";v="24", "Samsung Internet";v="27.0"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Samsung Internet',
|
||||
version : '27.0',
|
||||
major : '27',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: 'Yandex',
|
||||
headers : {
|
||||
'sec-ch-ua': '"Chromium";v="130", "YaBrowser";v="24.12", "Not?A_Brand";v="99", "Yowser";v="2.5"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Yandex',
|
||||
version : '24.12',
|
||||
major : '24',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
module.exports = UACHTests;
|
||||
@@ -271,6 +271,26 @@
|
||||
"major" : "11"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Bing",
|
||||
"ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/605.1.15 BingSapphire/31.8.430522001",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Bing",
|
||||
"version" : "31.8.430522001",
|
||||
"major" : "31"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Bing",
|
||||
"ua" : "Mozilla/5.0 (Linux; Android 9; MIX 2 Build/PKQ1.190118.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4893.0 Mobile Safari/537.36 BingWeb/6.9.12",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Bing",
|
||||
"version" : "6.9.12",
|
||||
"major" : "6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Blazer",
|
||||
"ua" : "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; PalmSource/hspr-H102; Blazer/4.0) 16;320x320",
|
||||
@@ -611,6 +631,16 @@
|
||||
"major" : "55"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "PaleMoon",
|
||||
"ua" : "(Windows NT 6.2; WOW64) KHTML/4.11 Gecko/20130308 Firefox/23.0 (PaleMoon/20.3)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "PaleMoon",
|
||||
"version" : "20.3",
|
||||
"major" : "20"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "PaleMoon",
|
||||
"ua" : "Mozilla/5.0 (X11; Linux x86_64; rv:52.9) Gecko/20100101 Goanna/3.4 Firefox/52.9 PaleMoon/27.6.1",
|
||||
@@ -1338,6 +1368,16 @@
|
||||
"major" : "5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Mozilla",
|
||||
"ua" : "Mozilla/2.02 [fr] (WinNT; I)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Mozilla",
|
||||
"version" : "2.02",
|
||||
"major" : "2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "MSIE",
|
||||
"ua" : "Mozilla/4.0 (compatible; MSIE 5.0b1; Mac_PowerPC)",
|
||||
@@ -1688,6 +1728,36 @@
|
||||
"major" : "2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Qwant",
|
||||
"ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 16_1_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) QwantMobile/6.7.6 Mobile/15E148 Safari/605.1.15",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Qwant",
|
||||
"version" : "6.7.6",
|
||||
"major" : "6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Qwant",
|
||||
"ua" : "QwantMobile/2.0 (Android 8.0.0; Mobile; rv:59.0) Gecko/59.0 Firefox/59.0 QwantBrowser/59.0",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Qwant",
|
||||
"version" : "59.0",
|
||||
"major" : "59"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Qwant",
|
||||
"ua" : "QwantMobile/2.0 (iPad; CPU OS 15_8_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) QwantiOS/2.7.0b1 Mobile/15E148 Safari/605.1.15",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Qwant",
|
||||
"version" : "2.0",
|
||||
"major" : "2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Rekonq 2",
|
||||
"ua" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.21 (KHTML, like Gecko) rekonq/2.2.1 Safari/537.21",
|
||||
@@ -2695,5 +2765,27 @@
|
||||
"major" : "10",
|
||||
"type" : "inapp"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Zalo on iOS",
|
||||
"ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 13_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Zalo/20.05.01 Mobile/15E148",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Zalo",
|
||||
"version" : "20.05.01",
|
||||
"major" : "20",
|
||||
"type" : "inapp"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Zalo on Android",
|
||||
"ua" : "Mozilla/5.0 (Linux; Android 10; Vsmart Live Build/QKQ1.190918.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Mobile Safari/537.36 Zalo/20.04.02.r1",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Zalo",
|
||||
"version" : "20.04.02.r1",
|
||||
"major" : "20",
|
||||
"type" : "inapp"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -87,6 +87,22 @@
|
||||
"architecture" : "amd64"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Alpha",
|
||||
"ua" : "Mozilla/3.01 (WinNT; I) [AXP]",
|
||||
"expect" :
|
||||
{
|
||||
"architecture" : "alpha"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Alpha",
|
||||
"ua" : "Mozilla/5.0 (X11; OpenBSD alpha; rv:78.0) Gecko/20100101 Firefox/78.0",
|
||||
"expect" :
|
||||
{
|
||||
"architecture" : "alpha"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "ARM",
|
||||
"ua" : "Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 635) like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537",
|
||||
@@ -273,7 +289,15 @@
|
||||
},
|
||||
{
|
||||
"desc" : "68k",
|
||||
"ua" : "'Mozilla/1.1 (Macintosh; U; 68K)'",
|
||||
"ua" : "Mozilla/1.1 (Macintosh; U; 68K)",
|
||||
"expect" :
|
||||
{
|
||||
"architecture" : "68k"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "MC680x0",
|
||||
"ua" : "AmigaVoyager/3.2 (AmigaOS/MC680x0)",
|
||||
"expect" :
|
||||
{
|
||||
"architecture" : "68k"
|
||||
|
||||
@@ -122,42 +122,6 @@
|
||||
"type": "undefined"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Philips SmartTV",
|
||||
"ua": "Opera/9.80 HbbTV/1.1.1 (; Philips; ; ; ; ) NETTV/4.0.2; en) Version/11.60",
|
||||
"expect": {
|
||||
"vendor": "Philips",
|
||||
"model": "",
|
||||
"type": "smarttv"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Philips 32PFL6606K/02 SmartTV (2011)",
|
||||
"ua": "Opera/9.80 (Linux mips ; U; HbbTV/1.1.1 (; Philips; ; ; ; ) CE-HTML/1.0 NETTV/3.1.0; en) Presto/2.6.33 Version/10.70",
|
||||
"expect": {
|
||||
"vendor": "Philips",
|
||||
"model": "",
|
||||
"type": "smarttv"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Philips 32PFL6606K/02 SmartTV (2013)",
|
||||
"ua": "Opera/9.80 (Linux mips ; U; HbbTV/1.1.1 (; Philips; ; ; ; ) CE-HTML/1.0 NETTV/3.1.0; en) Presto/2.6.33 Version/10.70",
|
||||
"expect": {
|
||||
"vendor": "Philips",
|
||||
"model": "",
|
||||
"type": "smarttv"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Philips 32PHS5301/12 SmartTV (2016)",
|
||||
"ua": "Mozilla/5.0 (Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36 OPR/29.0.1803.0 OMI/4.5.23.37.MOT2.13 HbbTV/1.2.1 (;Philips;32PHS5301/12;;_TV_MT5800;) Firmware/TPM161E_012.002.045.001 en",
|
||||
"expect": {
|
||||
"vendor": "Philips",
|
||||
"model": "32PHS5301/12",
|
||||
"type": "smarttv"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Samsung SmartTV",
|
||||
"ua": "Mozilla/5.0 (SMART-TV; X11; Linux armv7l) AppleWebkit/537.42 (KHTML, like Gecko) Safari/537.42",
|
||||
|
||||
@@ -44,6 +44,105 @@
|
||||
"type": "tablet"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "iPad using Chrome",
|
||||
"ua": "Mozilla/5.0 (iPad13,10; CPU OS 16_6_2 like Mac OS X) AppleWebKit/602.3 (KHTML, like Gecko) CriOS/97.0.0.5927.72 Mobile/11S296 Safari/602.3",
|
||||
"expect": {
|
||||
"vendor": "Apple",
|
||||
"model": "iPad",
|
||||
"type": "tablet"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "iPad using DuckDuckGo",
|
||||
"ua": "Mozilla/5.0 (iPad; iPad13,6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) DuckDuckGo/130.0.0.0 Mobile/15E148 Safari/604.1",
|
||||
"expect": {
|
||||
"vendor": "Apple",
|
||||
"model": "iPad",
|
||||
"type": "tablet"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "iPad using Discord",
|
||||
"ua": "Discord/52.0 (iPad; iOS 14.4; Scale/2.00)",
|
||||
"expect": {
|
||||
"vendor": "Apple",
|
||||
"model": "iPad",
|
||||
"type": "tablet"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "iPad using Firefox",
|
||||
"ua": "Mozilla/5.0 (iPad; iPad14,2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Firefox/120.0 Mobile/15E148 Safari/604.1",
|
||||
"expect": {
|
||||
"vendor": "Apple",
|
||||
"model": "iPad",
|
||||
"type": "tablet"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "iPad using iTunes",
|
||||
"ua": "itunesstored/1.0 iOS/15.6.1 model/iPad13,8 hwp/t8103 build/19G82 (5; dt:238)",
|
||||
"expect": {
|
||||
"vendor": "Apple",
|
||||
"model": "iPad",
|
||||
"type": "tablet"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "iPad using MS OneNote",
|
||||
"ua": "Microsoft Office OneNote/16.81/240108 (iOS/16.5.1; Tablet; AppStore; Apple/iPad8,3)",
|
||||
"expect": {
|
||||
"vendor": "Apple",
|
||||
"model": "iPad",
|
||||
"type": "tablet"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "iPad using MS Word",
|
||||
"ua": "Microsoft Office Word/2.44.1211 (iOS/13.7; Tablet; es-MX; AppStore; Apple/iPad11,3)",
|
||||
"expect": {
|
||||
"vendor": "Apple",
|
||||
"model": "iPad",
|
||||
"type": "tablet"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "iPad using Quora",
|
||||
"ua": "Quora 8.4.30 rv:3230 env:prod (iPad11,3; iPadOS 17.7; en_GB) AppleWebKit",
|
||||
"expect": {
|
||||
"vendor": "Apple",
|
||||
"model": "iPad",
|
||||
"type": "tablet"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "iPad using TuneIn Radio",
|
||||
"ua": "TuneIn Radio/27.1.0; iPad6,3; iPadOS/16.6",
|
||||
"expect": {
|
||||
"vendor": "Apple",
|
||||
"model": "iPad",
|
||||
"type": "tablet"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "iPad using TuneIn Radio Pro",
|
||||
"ua": "TuneIn Radio Pro/21.4.1; iPad8,9; iOS/15.0",
|
||||
"expect": {
|
||||
"vendor": "Apple",
|
||||
"model": "iPad",
|
||||
"type": "tablet"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "iPad using YouTube",
|
||||
"ua": "com.google.ios.youtube/20.31.6 (iPad13,5; U; CPU iPadOS 18_6 like Mac OS X; en_US)",
|
||||
"expect": {
|
||||
"vendor": "Apple",
|
||||
"model": "iPad",
|
||||
"type": "tablet"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "iPod",
|
||||
"ua": "Mozilla/5.0 (iPod touch; CPU iPhone OS 7_0_4 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B554a Safari/9537.53",
|
||||
@@ -62,6 +161,15 @@
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "iPhone using Spotify",
|
||||
"ua": "Spotify/8.7.70 iOS/16.0 (iPhone15,3)",
|
||||
"expect": {
|
||||
"vendor": "Apple",
|
||||
"model": "iPhone15,3",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "iPhone SE",
|
||||
"ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 [FBAN/FBIOS;FBDV/iPhone8,4;FBMD/iPhone;FBSN/iOS;FBSV/13.3.1;FBSS/2;FBID/phone;FBLC/en_US;FBOP/5;FBCR/]",
|
||||
|
||||
@@ -1,7 +1,25 @@
|
||||
[
|
||||
{
|
||||
"desc": "BlackBerry 9650",
|
||||
"ua": "Mozilla/5.0 (BlackBerry; U; BlackBerry 9650; en-US) AppleWebKit/534.8+ (KHTML, like Gecko) Version/6.0.0.524 Mobile Safari/534.8+",
|
||||
"expect": {
|
||||
"vendor": "BlackBerry",
|
||||
"model": "9650",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "BlackBerry 9780",
|
||||
"ua": "Mozilla/5.0 (BlackBerry; U; BlackBerry 9780; en) AppleWebKit/534.8+ (KHTML, like Gecko) Version/6.0.0.546 Mobile Safari/534.8+",
|
||||
"expect": {
|
||||
"vendor": "BlackBerry",
|
||||
"model": "9780",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "BlackBerry Priv",
|
||||
"ua": "User-Agent: Mozilla/5.0 (Linux; Android 5.1.1; STV100-1 Build/LMY47V; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/46.0.2490.76 Mobile Safari/537.36",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 5.1.1; STV100-1 Build/LMY47V; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/46.0.2490.76 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "BlackBerry",
|
||||
"model": "STV100-1",
|
||||
@@ -28,7 +46,7 @@
|
||||
},
|
||||
{
|
||||
"desc": "BlackBerry Key2 LE",
|
||||
"ua": "User-Agent: Mozilla/5.0 (Linux; Android 8.1.0; BBE100-1 Build/OPM1.171019.026) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497 Mobile Safari/537.36",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 8.1.0; BBE100-1 Build/OPM1.171019.026) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "BlackBerry",
|
||||
"model": "BBE100-1",
|
||||
|
||||
20
test/data/ua/device/hisense.json
Normal file
20
test/data/ua/device/hisense.json
Normal file
@@ -0,0 +1,20 @@
|
||||
[
|
||||
{
|
||||
"desc": "Hisense E50 Lite",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 11; Hisense E50 Lite) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.5249.126 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Hisense",
|
||||
"model": "E50 Lite",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Hisense V40s",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 11; Hisense V40s) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.5195.125 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Hisense",
|
||||
"model": "V40s",
|
||||
"type": "mobile"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -701,6 +701,15 @@
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Huawei P10 Lite",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 8.0.0; WAS-L03T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5199.205 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Huawei",
|
||||
"model": "WAS-L03T",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Huawei P20 Lite",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 8.0.0; ANE-LX1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.143 Mobile Safari/537.36",
|
||||
@@ -728,6 +737,15 @@
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Huawei P30",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 10; ELE-L04) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.109 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Huawei",
|
||||
"model": "ELE-L04",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Huawei P30",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 9; ELE-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.90 Mobile Safari/537.36",
|
||||
@@ -782,6 +800,15 @@
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Huawei Nova",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 7.0; HUAWEI CAN-L13) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.5113.212 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Huawei",
|
||||
"model": "CAN-L13",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Huawei Nova 5T",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 10; YAL-L21) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Mobile Safari/537.36",
|
||||
@@ -899,6 +926,15 @@
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Huawei Y7p",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 10; ART-L28; HMSCore 6.8.0.311) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4476.0 HuaweiBrowser/12.1.2.312 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Huawei",
|
||||
"model": "ART-L28",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Huawei Y7p",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 9; ART-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.92 Mobile Safari/537.36",
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"desc": "Nokia 1",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 10; Nokia 1 Build/QP1A.190711.020) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.15 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Nokia",
|
||||
"model": "1",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Nokia3xx",
|
||||
"ua": "Nokia303/14.87 CLDC-1.1",
|
||||
|
||||
83
test/data/ua/device/philips.json
Normal file
83
test/data/ua/device/philips.json
Normal file
@@ -0,0 +1,83 @@
|
||||
[
|
||||
{
|
||||
"desc": "Philips S616",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 5.1; Philips S616 Build/LMY47D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.109 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Philips",
|
||||
"model": "S616",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Philips W8510",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 4.2.2; Philips W8510 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.68 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Philips",
|
||||
"model": "W8510",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Philips SmartTV",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 11; PHILIPS 4k TV Build/RTXC.231010.082.A1; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/126.0.6478.71 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "PHILIPS",
|
||||
"model": "undefined",
|
||||
"type": "smarttv"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Philips SmartTV",
|
||||
"ua": "Opera/9.80 HbbTV/1.1.1 (; Philips; ; ; ; ) NETTV/4.0.2; en) Version/11.60",
|
||||
"expect": {
|
||||
"vendor": "Philips",
|
||||
"model": "",
|
||||
"type": "smarttv"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Philips 32PFL6606K/02 SmartTV (2011)",
|
||||
"ua": "Opera/9.80 (Linux mips ; U; HbbTV/1.1.1 (; Philips; ; ; ; ) CE-HTML/1.0 NETTV/3.1.0; en) Presto/2.6.33 Version/10.70",
|
||||
"expect": {
|
||||
"vendor": "Philips",
|
||||
"model": "",
|
||||
"type": "smarttv"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Philips 32PFL6606K/02 SmartTV (2013)",
|
||||
"ua": "Opera/9.80 (Linux mips ; U; HbbTV/1.1.1 (; Philips; ; ; ; ) CE-HTML/1.0 NETTV/3.1.0; en) Presto/2.6.33 Version/10.70",
|
||||
"expect": {
|
||||
"vendor": "Philips",
|
||||
"model": "",
|
||||
"type": "smarttv"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Philips 32PHS5301/12 SmartTV (2016)",
|
||||
"ua": "Mozilla/5.0 (Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36 OPR/29.0.1803.0 OMI/4.5.23.37.MOT2.13 HbbTV/1.2.1 (;Philips;32PHS5301/12;;_TV_MT5800;) Firmware/TPM161E_012.002.045.001 en",
|
||||
"expect": {
|
||||
"vendor": "Philips",
|
||||
"model": "32PHS5301/12",
|
||||
"type": "smarttv"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Philips PH0M_EA_T32",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 10; Philips FHD Android TV Build/QTG3.201102.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/125.0.6422.186 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Philips",
|
||||
"model": "undefined",
|
||||
"type": "smarttv"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Philips PH3M_AL_T32",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 11; Philips Google TV TA7 Build/RTM5.220609.199; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/111.0.5563.58 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Philips",
|
||||
"model": "undefined",
|
||||
"type": "smarttv"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -25,5 +25,23 @@
|
||||
"model": "Neo3 Link",
|
||||
"type": "xr"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Pico Neo 3",
|
||||
"ua": "Mozilla/5.0 (X11; Linux x86_64; Pico Neo 3 OS5.12.2 like Quest) AppleWebKit/537.36 (KHTML, like Gecko) PicoBrowser/3.3.48 Chrome/105.0.5195.68 VR Safari/537.36 OculusBrowser/7.0",
|
||||
"expect": {
|
||||
"vendor": "Pico",
|
||||
"model": "Neo 3",
|
||||
"type": "xr"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Pico Neo 3 Pro",
|
||||
"ua": "Mozilla/5.0 (X11; Linux x86_64; Pico Neo 3 Pro OS5.9.9.0 like Quest) AppleWebKit/537.36 (KHTML, like Gecko) PicoBrowser/3.3.46 Chrome/105.0.5195.68 VR Safari/537.36 OculusBrowser/7.0",
|
||||
"expect": {
|
||||
"vendor": "Pico",
|
||||
"model": "Neo 3 Pro",
|
||||
"type": "xr"
|
||||
}
|
||||
}
|
||||
]
|
||||
29
test/data/ua/device/wiko.json
Normal file
29
test/data/ua/device/wiko.json
Normal file
@@ -0,0 +1,29 @@
|
||||
[
|
||||
{
|
||||
"desc": "Wiko Life 3",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 11; Wiko U316AT) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5199.205 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Wiko",
|
||||
"model": "U316AT",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Wiko Ride 3",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 11; Wiko U614AS) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.181 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "Wiko",
|
||||
"model": "U614AS",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Wiko T10",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 11; WIKO T10 Build/RP1A.200720.011) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.62 Mobile Safari/537.36",
|
||||
"expect": {
|
||||
"vendor": "WIKO",
|
||||
"model": "T10",
|
||||
"type": "mobile"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -116,6 +116,15 @@
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Xiaomi Mi 11 Lite 5G",
|
||||
"ua": "Mozilla/5.0 (Linux; U; Android 12; zh-CN; Mi 11 Lite 5G Build/SKQ1.211006.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.136 Mobile Safari/537.36 XiaoMi/MiuiBrowser/13.17.0-gn",
|
||||
"expect": {
|
||||
"vendor": "Xiaomi",
|
||||
"model": "Mi 11 Lite 5G",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Xiaomi Mi 5s Plus",
|
||||
"ua": "Mozilla/5.0 (Linux; U; Android 6.0.1; zh-cn; MI 5s Plus Build/MXB48T) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.146 Mobile Safari/537.36 XiaoMi/MiuiBrowser/8.7.1",
|
||||
@@ -188,6 +197,15 @@
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Xiaomi Mi 10T",
|
||||
"ua": "Mozilla/5.0 (Linux; U; Android 12; fr-CA; Mi 10T Build/SKQ1.211006.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.79 Mobile Safari/537.36 XiaoMi/MiuiBrowser/13.16.1-gn",
|
||||
"expect": {
|
||||
"vendor": "Xiaomi",
|
||||
"model": "Mi 10T",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Xiaomi Mi A2",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 9; Mi A2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Mobile Safari/537.36",
|
||||
@@ -314,6 +332,15 @@
|
||||
"type": "tablet"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Xiaomi Pad 5",
|
||||
"ua": "Mozilla/5.0 (Linux; U; Android 12; ca-ES; Xiaomi Pad 5 Build/SKQ1.220303.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/89.0.4389.86 Mobile Safari/537.36 XiaoMi/MiuiBrowser/13.6.0-gn",
|
||||
"expect": {
|
||||
"vendor": "Xiaomi",
|
||||
"model": "mi Pad 5",
|
||||
"type": "tablet"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "Xiaomi Pad 6S Pro 12.4",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 14; 24018RPACC) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36",
|
||||
@@ -458,6 +485,15 @@
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "XiaoMi Redmi Note 10 Lite",
|
||||
"ua": "Mozilla/5.0 (Linux; U; Android 12; es-VE; Mi Note 10 Lite Build/SKQ1.210908.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.88 Mobile Safari/537.36 XiaoMi/MiuiBrowser/13.16.1-gn",
|
||||
"expect": {
|
||||
"vendor": "Xiaomi",
|
||||
"model": "Mi Note 10 Lite",
|
||||
"type": "mobile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "XiaoMi Redmi Note 10 Pro",
|
||||
"ua": "Mozilla/5.0 (Linux; Android 13; M2101K6P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Mobile Safari/537.36",
|
||||
|
||||
@@ -79,6 +79,26 @@
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Algolia Crawler",
|
||||
"ua" : "Algolia Crawler/v2.183.0",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Algolia Crawler",
|
||||
"version" : "v2.183.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Algolia Crawler Renderscript",
|
||||
"ua" : "Algolia Crawler Renderscript",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Algolia Crawler Renderscript",
|
||||
"version" : "undefined",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Applebot",
|
||||
"ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 8_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B410 Safari/600.1.4 (Applebot/0.1;+http://www.apple.com/go/applebot)",
|
||||
@@ -139,6 +159,16 @@
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Baidu ADS",
|
||||
"ua" : "Baidu-ADS",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Baidu-ADS",
|
||||
"version" : "undefined",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Baiduspider",
|
||||
"ua" : "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)",
|
||||
@@ -229,6 +259,36 @@
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "BLEXBot",
|
||||
"ua" : "Mozilla/5.0 (compatible; BLEXBot/1.0; +http://webmeup-crawler.com/)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "BLEXBot",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "botify",
|
||||
"ua" : "Desktop: Mozilla/5.0 (compatible; botify; http://botify.com)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "botify",
|
||||
"version" : "undefined",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Bravebot",
|
||||
"ua" : "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; Bravebot/1.0; +https://search.brave.com/help/brave-search-crawler) Chrome/W.X.Y.Z Safari/537.36",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Bravebot",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Bytespider",
|
||||
"ua" : "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.1511.1269 Mobile Safari/537.36; Bytespider",
|
||||
@@ -269,6 +329,26 @@
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Claude-SearchBot",
|
||||
"ua" : "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; Claude-SearchBot/1.0; +Claude-SearchBot@anthropic.com)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Claude-SearchBot",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "ClaudeWeb",
|
||||
"ua" : "Claude-Web/1.0 (web crawler; +https://www.anthropic.com/; bots@anthropic.com)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Claude-Web",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Coc Coc Bot (web)",
|
||||
"ua" : "Mozilla/5.0 (compatible; coccocbot-web/1.0; +http://help.coccoc.com/searchengine)",
|
||||
@@ -290,15 +370,55 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "ClaudeWeb",
|
||||
"ua" : "Claude-Web/1.0 (web crawler; +https://www.anthropic.com/; bots@anthropic.com)",
|
||||
"desc" : "cohere-training-data-crawler",
|
||||
"ua" : "cohere-training-data-crawler (+crawler@cohere.ai)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Claude-Web",
|
||||
"name" : "cohere-training-data-crawler",
|
||||
"version" : "undefined",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "contxbot",
|
||||
"ua" : "Mozilla/5.0 (compatible;contxbot/1.0)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "contxbot",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Cotoyogi",
|
||||
"ua" : "Mozilla/5.0 (compatible; Cotoyogi/4.0; +https://ds.rois.ac.jp/center8/crawler/)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Cotoyogi",
|
||||
"version" : "4.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Coveobot",
|
||||
"ua" : "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko) (compatible; Coveobot/2.0;+http://www.coveo.com/bot.html)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Coveobot",
|
||||
"version" : "2.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "CriteoBot",
|
||||
"ua" : "CriteoBot/0.1 (+https://www.criteo.com/criteo-crawler/)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "CriteoBot",
|
||||
"version" : "0.1",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "DataForSEO",
|
||||
"ua" : "Mozilla/5.0 (compatible; DataForSeoBot; +https://dataforseo.com/dataforseo-bot)",
|
||||
@@ -339,6 +459,16 @@
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "DeepSeekBot",
|
||||
"ua" : "DeepSeekBot",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "DeepSeekBot",
|
||||
"version" : "undefined",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Diffbot",
|
||||
"ua" : "Diffbot/0.1",
|
||||
@@ -369,6 +499,26 @@
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "DuckDuckGo-Favicons-Bot",
|
||||
"ua" : "DuckDuckGo-Favicons-Bot/1.0",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "DuckDuckGo-Favicons-Bot",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Elastic",
|
||||
"ua" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/124.0.6367.29 Safari/537.36 Elastic/Synthetics",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Elastic",
|
||||
"version" : "undefined",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Exabot",
|
||||
"ua" : "Mozilla/5.0 (compatible; Exabot/3.0; +http://www.exabot.com/go/robot)",
|
||||
@@ -409,6 +559,36 @@
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "FirecrawlAgent",
|
||||
"ua" : "Mozilla/5.0 (compatible; FirecrawlAgent/1.0)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "FirecrawlAgent",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Freespoke",
|
||||
"ua" : "Mozilla/5.0 (compatible; Freespoke/2.0; +https://docs.freespoke.com/search/bot)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Freespoke",
|
||||
"version" : "2.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "APIs-Google",
|
||||
"ua" : "APIs-Google (+https://developers.google.com/webmasters/APIs-Google.html)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "APIs-Google",
|
||||
"version" : "undefined",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Googlebot-Video",
|
||||
"ua" : "Googlebot-Video/1.0",
|
||||
@@ -509,6 +689,16 @@
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Google-CloudVertexBot",
|
||||
"ua" : "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.7204.183 Mobile Safari/537.36 (compatible; Google-CloudVertexBot; +https://cloud.google.com/enterprise-search)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Google-CloudVertexBot",
|
||||
"version" : "undefined",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Google-Safety",
|
||||
"ua" : "Google-Safety",
|
||||
@@ -529,6 +719,16 @@
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "HuggingFace-Bot",
|
||||
"ua" : "Mozilla/5.0 (compatible; HuggingFace-Bot/1.0; +https://huggingface.co/)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "HuggingFace-Bot",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "iAskBot",
|
||||
"ua" : "Mozilla/5.0 AppleWebKit/605.1.15 (KHTML, like Gecko; compatible; iAskBot/1.0; +https://iask.ai/) Chrome/120.0.6099.119 Safari/605.1.15",
|
||||
@@ -549,6 +749,26 @@
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Kagibot",
|
||||
"ua" : "Mozilla/5.0 (compatible; Kagibot/1.0; +https://kagi.com/bot)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Kagibot",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Kangaroo Bot",
|
||||
"ua" : "Mozilla/5.0 (compatible; Kangaroo Bot/1.0)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Kangaroo Bot",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Linespider",
|
||||
"ua" : "Mozilla/5.0 (compatible; Linespider/1.1; +https://lin.ee/4dwXkTH)",
|
||||
@@ -579,6 +799,16 @@
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Marginalia Search",
|
||||
"ua" : "search.marginalia.nu",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "marginalia",
|
||||
"version" : "undefined",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Meta-ExternalAgent",
|
||||
"ua" : "meta-externalagent/1.1 (+https://developers.facebook.com/docs/sharing/webmasters/crawler)",
|
||||
@@ -610,6 +840,16 @@
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "msnbot",
|
||||
"ua" : "msnbot/2.0b (+http://search.msn.com/msnbot.htm)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "msnbot",
|
||||
"version" : "2.0b",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Omgili",
|
||||
"ua" : "omgili/0.5 +https://omgili.com",
|
||||
@@ -630,6 +870,16 @@
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "OnCrawl",
|
||||
"ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12F70 Safari/600.1.4 (compatible; OnCrawl Mobile/1.0; +http://www.oncrawl.com/)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "OnCrawl",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Onespot",
|
||||
"ua" : "Mozilla/5.0 (compatible; Onespot-ScraperBot/1.0; +https://www.onespot.com/identifying-traffic.html)",
|
||||
@@ -650,6 +900,16 @@
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "PanguBot",
|
||||
"ua" : "Mozilla/5.0 (compatible; PanguBot/1.0)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "PanguBot",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "PerplexityBot",
|
||||
"ua" : "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; PerplexityBot/1.0; +https://perplexity.ai/perplexitybot)",
|
||||
@@ -705,11 +965,51 @@
|
||||
"ua" : "Mozilla/5.0 (compatible; Qwantbot-news/2.0; +https://help.qwant.com/bot/)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Qwantbot",
|
||||
"name" : "Qwantbot-news",
|
||||
"version" : "2.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Replicate-Bot",
|
||||
"ua" : "Mozilla/5.0 (compatible; Replicate-Bot/1.0; +https://replicate.com/)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Replicate-Bot",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "RunPod-Bot",
|
||||
"ua" : "Mozilla/5.0 (compatible; RunPod-Bot/1.0; +https://runpod.io/)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "RunPod-Bot",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "SBIntuitionsBot",
|
||||
"ua" : "Mozilla/5.0 (compatible; SBIntuitionsBot/0.1;+https://www.sbintuitions.co.jp/bot/)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "SBIntuitionsBot",
|
||||
"version" : "0.1",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "SeekportBot",
|
||||
"ua" : "Mozilla/5.0 (compatible; SeekportBot; +https://bot.seekport.com)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "SeekportBot",
|
||||
"version" : "undefined",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "SemrushBot",
|
||||
"ua" : "Mozilla/5.0 (compatible; SemrushBot/7~bl; +http://www.semrush.com/bot.html)",
|
||||
@@ -761,7 +1061,27 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Sogou",
|
||||
"desc" : "Siteimprove",
|
||||
"ua" : "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; SiteCheck-sitecrawl by Siteimprove.com; +https://siteimprove.com/bots) Chrome/[VERSION] Safari/537.36",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Siteimprove",
|
||||
"version" : "undefined",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Sogou Pic Spider",
|
||||
"ua" : "Sogou Pic Spider/3.0( http://www.sogou.com/docs/help/webmasters.htm#07)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Sogou Pic Spider",
|
||||
"version" : "3.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Sogou web spider",
|
||||
"ua" : "Sogou web spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07)",
|
||||
"expect" :
|
||||
{
|
||||
@@ -780,6 +1100,26 @@
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "SurdotlyBot",
|
||||
"ua" : "Mozilla/5.0 (compatible; SurdotlyBot/1.0; +http://sur.ly/bot.html)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "SurdotlyBot",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Swiftbot",
|
||||
"ua" : "Swiftbot/1.0 (swiftype.com)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Swiftbot",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Teoma",
|
||||
"ua" : "Mozilla/2.0 (compatible; Ask Jeeves/Teoma; +http://sp.ask.com/docs/about/tech_crawling.html)",
|
||||
@@ -790,6 +1130,16 @@
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "TikTokSpider",
|
||||
"ua" : "Mozilla/5.0 (Linux; Android 5.0) AppleWebKit/537.36 (KHTML, like Gecko) Mobile Safari/537.36 (compatible; TikTokSpider; ttspider-feedback@tiktok.com)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "TikTokSpider",
|
||||
"version" : "undefined",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Timpibot",
|
||||
"ua" : "Timpibot/0.8 (+http://www.timpi.io)",
|
||||
@@ -800,6 +1150,16 @@
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Together-Bot",
|
||||
"ua" : "Mozilla/5.0 (compatible; Together-Bot/1.0; +https://together.ai/)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Together-Bot",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "TurnitinBot",
|
||||
"ua" : "TurnitinBot (https://turnitin.com/robot/crawlerinfo.html)",
|
||||
@@ -810,6 +1170,26 @@
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "TwinAgent",
|
||||
"ua" : "TwinAgent/1.0",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "TwinAgent",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "xAI-Bot",
|
||||
"ua" : "Mozilla/5.0 (compatible; xAI-Bot/1.0; +https://x.ai/)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "xAI-Bot",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "VelenPublicWebCrawler",
|
||||
"ua" : "Mozilla/5.0 (compatible; VelenPublicWebCrawler/1.0; +https://velen.io)",
|
||||
@@ -820,6 +1200,36 @@
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "v0bot",
|
||||
"ua" : "v0bot",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "v0bot",
|
||||
"version" : "undefined",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "webzio",
|
||||
"ua" : "webzio (+https://webz.io/bot.html)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "webzio",
|
||||
"version" : "undefined",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Webzio-Extended",
|
||||
"ua" : "Mozilla/5.0 (compatible; Webzio-Extended/1.0; +https://www.webzio.com/bot.html)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Webzio-Extended",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Yahoo! Japan",
|
||||
"ua" : "Y!J-BRW/1.0 (https://www.yahoo-help.jp/app/answers/detail/p/595/a_id/42716)",
|
||||
@@ -840,6 +1250,46 @@
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexAccessibilityBot",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexAccessibilityBot/3.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexAccessibilityBot",
|
||||
"version" : "3.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexAdditionalBot",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexAdditionalBot/3.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexAdditionalBot",
|
||||
"version" : "3.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexAdNet",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexAdNet/1.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexAdNet",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexBlogs",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexBlogs/0.99; robot; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexBlogs",
|
||||
"version" : "0.99",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexBot",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)",
|
||||
@@ -850,6 +1300,256 @@
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexBot MirrorDetector",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexBot/3.0; MirrorDetector; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexBot MirrorDetector",
|
||||
"version" : "3.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexComBot",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexComBot/3.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexComBot",
|
||||
"version" : "3.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexFavicons",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexFavicons/1.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexFavicons",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexImageResizer",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexImageResizer/2.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexImageResizer",
|
||||
"version" : "2.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexImages",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexImages/3.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexImages",
|
||||
"version" : "3.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexMarket",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexMarket/1.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexMarket",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexMetrika",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexMetrika/2.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexMetrika",
|
||||
"version" : "2.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexMedia",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexMedia/3.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexMedia",
|
||||
"version" : "3.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexMobileBot",
|
||||
"ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 8_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B411 Safari/600.1.4 (compatible; YandexMobileBot/3.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexMobileBot",
|
||||
"version" : "3.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexMobileScreenShotBot",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexMobileScreenShotBot/1.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexMobileScreenShotBot",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexNews",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexNews/4.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexNews",
|
||||
"version" : "4.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexOntoDB",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexOntoDB/1.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexOntoDB",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexOntoDBAPI",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexOntoDBAPI/1.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexOntoDBAPI",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexPartner",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexPartner/3.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexPartner",
|
||||
"version" : "3.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexRCA",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexRCA/1.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexRCA",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexRenderResourcesBot",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexRenderResourcesBot/1.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexRenderResourcesBot",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexScreenshotBot",
|
||||
"ua" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.96 Safari/537.36 (compatible; YandexScreenshotBot/3.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexScreenshotBot",
|
||||
"version" : "3.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexSpravBot",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexSpravBot/1.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexSpravBot",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexTracker",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexTracker/1.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexTracker",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexVertis",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexVertis/3.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexVertis",
|
||||
"version" : "3.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexVerticals",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexVerticals/1.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexVerticals",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexVideo",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexVideo/3.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexVideo",
|
||||
"version" : "3.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexVideoParser",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexVideoParser/1.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexVideoParser",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexWebmaster",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexWebmaster/2.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexWebmaster",
|
||||
"version" : "2.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YepBot",
|
||||
"ua" : "Mozilla/5.0 (compatible; YepBot/1.0; +http://yep.com/yepbot/)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YepBot",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Yeti",
|
||||
"ua" : "Mozilla/5.0 (compatible; Yeti/1.1; +http://naver.me/spd)",
|
||||
@@ -889,5 +1589,15 @@
|
||||
"version" : "undefined",
|
||||
"type" : "crawler"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "ZumBot",
|
||||
"ua" : "Mozilla/5.0 (compatible; ZumBot/1.0; http://help.zum.com/inquiry)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "ZumBot",
|
||||
"version" : "1.0",
|
||||
"type" : "crawler"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -9,6 +9,16 @@
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Asana",
|
||||
"ua" : "Asana/1.4.0 WebsiteMetadataRetriever",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Asana",
|
||||
"version" : "1.4.0",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Better Uptime Bot",
|
||||
"ua" : "Better Uptime Bot Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36",
|
||||
@@ -29,6 +39,26 @@
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Bit.ly",
|
||||
"ua" : "bitlybot/3.0 (+http://bit.ly/)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "bitlybot",
|
||||
"version" : "3.0",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Blueno",
|
||||
"ua" : "facebookexternalhit/1.1 (compatible; Blueno/1.0; +http://naver.me/scrap)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Blueno",
|
||||
"version" : "1.0",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Bluesky",
|
||||
"ua" : "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; Bluesky Cardyb/1.1; +mailto:support@bsky.app) Chrome/100.0.0.0 Safari/537.36",
|
||||
@@ -39,6 +69,16 @@
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "BufferLinkPreviewBot",
|
||||
"ua" : "BufferLinkPreviewBot/1.0 (+https://scraper.buffer.com/about/bots/link-preview-bot)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "BufferLinkPreviewBot",
|
||||
"version" : "1.0",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "ChatGPT-User",
|
||||
"ua" : "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; ChatGPT-User/1.0; +https://openai.com/bot",
|
||||
@@ -49,6 +89,46 @@
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Chrome-Lighthouse",
|
||||
"ua" : "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4590.2 Mobile Safari/537.36 Chrome-Lighthouse",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Chrome-Lighthouse",
|
||||
"version" : "undefined",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Claude-User",
|
||||
"ua" : "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; Claude-User/1.0; +Claude-User@anthropic.com)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Claude-User",
|
||||
"version" : "1.0",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Cohere-AI",
|
||||
"ua" : "Mozilla/5.0 (compatible; Cohere-AI/1.0; +https://cohere.com/)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Cohere-AI",
|
||||
"version" : "1.0",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Discordbot",
|
||||
"ua" : "Mozilla/5.0 (compatible; Discordbot/2.0; +https://discordapp.com)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Discordbot",
|
||||
"version" : "2.0",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "DuckAssistBot",
|
||||
"ua" : "DuckAssistBot/1.2; (+http://duckduckgo.com/duckassistbot.html)",
|
||||
@@ -59,6 +139,16 @@
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Gemini-Deep-Research",
|
||||
"ua" : "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; Gemini-Deep-Research; +https://gemini.google/overview/deep-research/) Chrome/135.0.0.0 Safari/537.36",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Gemini-Deep-Research",
|
||||
"version" : "undefined",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Google FeedFetcher",
|
||||
"ua" : "FeedFetcher-Google; (+http://www.google.com/feedfetcher.html)",
|
||||
@@ -129,6 +219,16 @@
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "HubSpot Page Fetcher",
|
||||
"ua" : "HubSpot Page Fetcher/1.0 http://www.hubspot.com/ web-crawlers@hubspot.com",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "HubSpot Page Fetcher",
|
||||
"version" : "1.0",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Iframely",
|
||||
"ua" : "Iframely/1.3.1 (+https://iframely.com/docs/about)",
|
||||
@@ -139,6 +239,26 @@
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "kakaotalk-scrap",
|
||||
"ua" : "facebookexternalhit/1.1; kakaotalk-scrap/1.0; +https://devtalk.kakao.com/t/scrap/33984",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "kakaotalk-scrap",
|
||||
"version" : "1.0",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "KeybaseBot",
|
||||
"ua" : "Mozilla/5.0 (compatible; KeybaseBot; +https://keybase.io)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "KeybaseBot",
|
||||
"version" : "undefined",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Meta-ExternalFetcher",
|
||||
"ua" : "meta-externalfetcher/1.1 (+https://developers.facebook.com/docs/sharing/webmasters/crawler)",
|
||||
@@ -209,6 +329,36 @@
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Slack-ImgProxy",
|
||||
"ua" : "Slack-ImgProxy 0.19 (+https://api.slack.com/robots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Slack-ImgProxy",
|
||||
"version" : "0.19",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Slackbot",
|
||||
"ua" : "Slackbot 1.0 (+https://api.slack.com/robots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Slackbot",
|
||||
"version" : "1.0",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Slackbot-LinkExpanding",
|
||||
"ua" : "Slackbot-LinkExpanding 1.0 (+https://api.slack.com/robots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Slackbot-LinkExpanding",
|
||||
"version" : "1.0",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Snap URL Preview",
|
||||
"ua" : "Snap URL Preview Service; bot; snapchat; https://developers.snap.com/robots ",
|
||||
@@ -239,6 +389,16 @@
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Twitterbot",
|
||||
"ua" : "Twitterbot/1.0",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Twitterbot",
|
||||
"version" : "1.0",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "UptimeRobot",
|
||||
"ua" : "Mozilla/5.0 (compatible; UptimeRobot/2.0; http://www.uptimerobot.com/)",
|
||||
@@ -249,6 +409,26 @@
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "vercel-favicon-bot",
|
||||
"ua" : "vercel-favicon-bot",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "vercel-favicon-bot",
|
||||
"version" : "undefined",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "vercel-screenshot-bot",
|
||||
"ua" : "vercel-screenshot-bot",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "vercel-screenshot-bot",
|
||||
"version" : "undefined",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Vercelbot",
|
||||
"ua" : "Vercelbot (+https://vercel.com)",
|
||||
@@ -259,6 +439,26 @@
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "vercelflags",
|
||||
"ua" : "vercelflags",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "vercelflags",
|
||||
"version" : "undefined",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "verceltracing",
|
||||
"ua" : "verceltracing",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "verceltracing",
|
||||
"version" : "undefined",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "WhatsApp",
|
||||
"ua" : "WhatsApp/2.23.20.0",
|
||||
@@ -268,5 +468,105 @@
|
||||
"version" : "2.23.20.0",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YaDirectFetcher",
|
||||
"ua" : "Mozilla/5.0 (compatible; YaDirectFetcher/1.0; Dyatel; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YaDirectFetcher",
|
||||
"version" : "1.0",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexCalendar",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexCalendar/1.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexCalendar",
|
||||
"version" : "1.0",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexDirect",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexDirect/3.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexDirect",
|
||||
"version" : "3.0",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexDirectDyn",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexDirectDyn/1.0; +http://yandex.com/bots",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexDirectDyn",
|
||||
"version" : "1.0",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexForDomain",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexForDomain/1.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexForDomain",
|
||||
"version" : "1.0",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexPagechecker",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexPagechecker/1.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexPagechecker",
|
||||
"version" : "1.0",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexSearchShop",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexSearchShop/1.0; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexSearchShop",
|
||||
"version" : "1.0",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexSitelinks",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexSitelinks; Dyatel; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexSitelinks",
|
||||
"version" : "undefined",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "YandexUserproxy",
|
||||
"ua" : "Mozilla/5.0 (compatible; YandexUserproxy; robot; +http://yandex.com/bots)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "YandexUserproxy",
|
||||
"version" : "undefined",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "Zoombot",
|
||||
"ua" : "Mozilla/5.0 (compatible; Zoombot/1.0; +https://zoom.us; crawler@domain.com)",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "Zoombot",
|
||||
"version" : "1.0",
|
||||
"type" : "fetcher"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1,4 +1,22 @@
|
||||
[
|
||||
{
|
||||
"desc" : "iOS 18.6",
|
||||
"ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 18_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Mobile/15E148 Safari/604.1",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "iOS",
|
||||
"version" : "18.6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "iOS 26",
|
||||
"ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 18_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "iOS",
|
||||
"version" : "26.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "iOS in App",
|
||||
"ua" : "AppName/version CFNetwork/version Darwin/version",
|
||||
@@ -17,6 +35,15 @@
|
||||
"version" : "5.1.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "iOS with DuckDuckGo",
|
||||
"ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 18_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1 Ddg/26.0",
|
||||
"expect" :
|
||||
{
|
||||
"name" : "iOS",
|
||||
"version" : "18.7"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "iOS with Opera Mini",
|
||||
"ua" : "Opera/9.80 (iPhone; Opera Mini/7.1.32694/27.1407; U; en) Presto/2.8.119 Version/11.10",
|
||||
@@ -35,6 +62,33 @@
|
||||
"version" : "13.6.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "iOS with Instagram",
|
||||
"ua": "Instagram 5.0.2 (iPhone5,1; iPhone OS 7_0_4; en_US; en) AppleWebKit/420+",
|
||||
"expect":
|
||||
{
|
||||
"name" : "iOS",
|
||||
"version" : "7.0.4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "iOS with MS Word App",
|
||||
"ua": "Microsoft Office Word/2.44.1211 (iOS/13.7; Tablet; es-MX; AppStore; Apple/iPad11,3)",
|
||||
"expect":
|
||||
{
|
||||
"name" : "iOS",
|
||||
"version" : "13.7"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "iOS with Quora App",
|
||||
"ua": "Quora 8.4.30 rv:3230 env:prod (iPad11,3; iPadOS 17.7; en_GB) AppleWebKit",
|
||||
"expect":
|
||||
{
|
||||
"name" : "iOS",
|
||||
"version" : "17.7"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "iOS with Slack App",
|
||||
"ua": "com.tinyspeck.chatlyio/23.04.10 (iPhone; iOS 16.4.1; Scale/3.00)",
|
||||
@@ -44,6 +98,33 @@
|
||||
"version" : "16.4.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "iOS with Snapchat",
|
||||
"ua": "Snapchat/12.12.1.40 (iPhone15,2; iOS 16.2; gzip)",
|
||||
"expect":
|
||||
{
|
||||
"name" : "iOS",
|
||||
"version" : "16.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "iOS with Spotify App",
|
||||
"ua": "Spotify/8.7.70 iOS/16.0 (iPhone15,3)",
|
||||
"expect":
|
||||
{
|
||||
"name" : "iOS",
|
||||
"version" : "16.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc": "iOS with TuneIn Radio App",
|
||||
"ua": "TuneIn Radio/27.1.0; iPad6,3; iPadOS/16.6",
|
||||
"expect":
|
||||
{
|
||||
"name" : "iOS",
|
||||
"version" : "16.6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"desc" : "iOS BE App",
|
||||
"ua" : "APP-BE Test/1.0 (iPad; Apple; CPU iPhone OS 7_0_2 like Mac OS X)",
|
||||
|
||||
37
test/unit/cli/cli.spec.js
Normal file
37
test/unit/cli/cli.spec.js
Normal file
@@ -0,0 +1,37 @@
|
||||
const assert = require('node:assert');
|
||||
const { exec } = require('node:child_process');
|
||||
const fs = require('node:fs');
|
||||
const { UAParser } = require('../../../src/main/ua-parser');
|
||||
const uap = new UAParser();
|
||||
|
||||
const input = [
|
||||
'Opera/9.25 (Windows NT 6.0; U; ru)',
|
||||
'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
|
||||
];
|
||||
const output = input.map(x => uap.setUA(x).getResult());
|
||||
|
||||
describe('npx ua-parser-js <string>', () => {
|
||||
it ('print result to stdout', () => {
|
||||
exec('node ./script/cli.js "TEST"', (err, stdout, stderr) => {
|
||||
assert.deepEqual(JSON.parse(stdout), JSON.parse(JSON.stringify([uap.setUA("TEST").getResult()])));
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
describe('npx ua-parser-js --input-file=<filepath>', () => {
|
||||
it ('load file and print result to stdout', () => {
|
||||
exec('node ./script/cli.js --input-file="../test/unit/cli/input.txt"', (err, stdout, stderr) => {
|
||||
assert.deepEqual(JSON.parse(stdout), JSON.parse(JSON.stringify(output)));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('npx ua-parser-js --input-file=<filepath> --output-file=<filepath>', () => {
|
||||
it ('load file and save result to file', () => {
|
||||
exec('node ./script/cli.js --input-file="../test/unit/cli/input.txt" --output-file="../test/unit/cli/output.json"', (err, stdout, stderr) => {
|
||||
fs.readFile('test/unit/cli/output.json', (err, data) => {
|
||||
assert.deepEqual(JSON.parse(data), JSON.parse(JSON.stringify(output)));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
2
test/unit/cli/input.txt
Normal file
2
test/unit/cli/input.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
Opera/9.25 (Windows NT 6.0; U; ru)
|
||||
Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)
|
||||
32
test/unit/cli/output.json
Normal file
32
test/unit/cli/output.json
Normal file
@@ -0,0 +1,32 @@
|
||||
[
|
||||
{
|
||||
"ua": "Opera/9.25 (Windows NT 6.0; U; ru)",
|
||||
"browser": {
|
||||
"name": "Opera",
|
||||
"version": "9.25",
|
||||
"major": "9"
|
||||
},
|
||||
"cpu": {},
|
||||
"device": {},
|
||||
"engine": {},
|
||||
"os": {
|
||||
"name": "Windows",
|
||||
"version": "Vista"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ua": "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)",
|
||||
"browser": {
|
||||
"name": "IE",
|
||||
"version": "5.5",
|
||||
"major": "5"
|
||||
},
|
||||
"cpu": {},
|
||||
"device": {},
|
||||
"engine": {},
|
||||
"os": {
|
||||
"name": "Windows",
|
||||
"version": "NT"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1,5 +1,5 @@
|
||||
import { UAParser } from '../../src/main/ua-parser.mjs';
|
||||
import { CPU, Device, Engine } from '../../src/enums/ua-parser-enums.mjs';
|
||||
import { CPUArch, DeviceType, EngineName } from '../../src/enums/ua-parser-enums.mjs';
|
||||
import * as assert from 'assert';
|
||||
|
||||
describe('Returns', () => {
|
||||
@@ -19,8 +19,8 @@ describe('Returns', () => {
|
||||
describe('Enums', () => {
|
||||
it('Can use enum', () => {
|
||||
const { cpu, device, engine } = UAParser('Mozilla/5.0 (X11; U; Linux armv7l; en-GB; rv:1.9.2a1pre) Gecko/20090928 Firefox/3.5 Maemo Browser 1.4.1.22 RX-51 N900');
|
||||
assert.strictEqual(cpu.is(CPU.ARM), true);
|
||||
assert.strictEqual(device.is(Device.MOBILE), true);
|
||||
assert.strictEqual(engine.is(Engine.GECKO), true);
|
||||
assert.strictEqual(cpu.is(CPUArch.ARM), true);
|
||||
assert.strictEqual(device.is(DeviceType.MOBILE), true);
|
||||
assert.strictEqual(engine.is(EngineName.GECKO), true);
|
||||
});
|
||||
});
|
||||
@@ -5,6 +5,8 @@ const traverse = require('@babel/traverse').default;
|
||||
const safe = require('safe-regex');
|
||||
const { UAParser } = require('../../src/main/ua-parser');
|
||||
const { Bots, CLIs, Crawlers, Emails, Fetchers, InApps, Libraries, Vehicles } = require('../../src/extensions/ua-parser-extensions');
|
||||
const { BrowserType, OSName, Extension } = require('../../src/enums/ua-parser-enums');
|
||||
const { CLI, Crawler, Email, Fetcher, Library } = Extension.BrowserName;
|
||||
|
||||
describe('Extensions', () => {
|
||||
[
|
||||
@@ -42,29 +44,29 @@ describe('Extensions', () => {
|
||||
const jsdom = 'Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/20.0.3';
|
||||
const scrapy = 'Scrapy/1.5.0 (+https://scrapy.org)';
|
||||
|
||||
assert.equal(UAParser(scrapy, Bots).browser.name, 'Scrapy');
|
||||
assert.equal(UAParser(scrapy, Bots).browser.name, Library.SCRAPY);
|
||||
|
||||
const emailParser = new UAParser(Emails);
|
||||
assert.deepEqual(emailParser.setUA(outlook).getBrowser(), {name: "Microsoft Outlook", version: "16.0.9126", major: "16", type: "email"});
|
||||
assert.deepEqual(emailParser.setUA(thunderbird).getBrowser(), {name: "Thunderbird", version: "78.13.0", major: "78", type: "email"});
|
||||
assert.deepEqual(emailParser.setUA(outlook).getBrowser(), {name: Email.MICROSOFT_OUTLOOK, version: "16.0.9126", major: "16", type: BrowserType.EMAIL});
|
||||
assert.deepEqual(emailParser.setUA(thunderbird).getBrowser(), {name: Email.THUNDERBIRD, version: "78.13.0", major: "78", type: BrowserType.EMAIL});
|
||||
|
||||
const libraryParser = new UAParser(Libraries);
|
||||
assert.deepEqual(libraryParser.setUA(axios).getBrowser(), {name: "axios", version: "1.3.5", major: "1", type: "library"});
|
||||
assert.deepEqual(libraryParser.setUA(jsdom).getBrowser(), {name: "jsdom", version: "20.0.3", major: "20", type: "library"});
|
||||
assert.deepEqual(libraryParser.setUA(scrapy).getBrowser(), {name: "Scrapy", version: "1.5.0", major: "1", type: "library"});
|
||||
assert.deepEqual(libraryParser.setUA(axios).getBrowser(), {name: Library.AXIOS, version: "1.3.5", major: "1", type: BrowserType.LIBRARY});
|
||||
assert.deepEqual(libraryParser.setUA(jsdom).getBrowser(), {name: Library.JSDOM, version: "20.0.3", major: "20", type: BrowserType.LIBRARY});
|
||||
assert.deepEqual(libraryParser.setUA(scrapy).getBrowser(), {name: Library.SCRAPY, version: "1.5.0", major: "1", type: BrowserType.LIBRARY});
|
||||
|
||||
// Bluesky
|
||||
const bluesky = 'Mozilla/5.0 (compatible; Bluesky Cardyb/1.1; +mailto:support@bsky.app)';
|
||||
assert.deepEqual(new UAParser(bluesky, Bots).getBrowser(), {
|
||||
name: 'Bluesky',
|
||||
name: Fetcher.BLUESKY,
|
||||
version: '1.1',
|
||||
major: '1',
|
||||
type: 'fetcher'
|
||||
type: BrowserType.FETCHER
|
||||
});
|
||||
|
||||
const whatsapp = "WhatsApp/2.0 A";
|
||||
assert.deepEqual(new UAParser(whatsapp, Fetchers).getOS(), {
|
||||
name : 'Android',
|
||||
name : OSName.ANDROID,
|
||||
version : undefined
|
||||
});
|
||||
});
|
||||
@@ -77,14 +79,14 @@ describe('Merge', () => {
|
||||
// try merging crawlers & CLIs
|
||||
const crawlersAndCLIs = { browser : [...Crawlers.browser, ...CLIs.browser]};
|
||||
const crawlersAndCLIsParser = new UAParser(crawlersAndCLIs);
|
||||
assert.deepEqual(crawlersAndCLIsParser.setUA(wget).getBrowser(), {name: "Wget", version: "1.21.1", major: "1", type:"cli"});
|
||||
assert.deepEqual(crawlersAndCLIsParser.setUA(facebookBot).getBrowser(), {name: "FacebookBot", version: "1.0", major: "1", type:"crawler"});
|
||||
assert.deepEqual(crawlersAndCLIsParser.setUA(wget).getBrowser(), {name: CLI.WGET, version: "1.21.1", major: "1", type: BrowserType.CLI});
|
||||
assert.deepEqual(crawlersAndCLIsParser.setUA(facebookBot).getBrowser(), {name: Crawler.META_FACEBOOKBOT, version: "1.0", major: "1", type: BrowserType.CRAWLER});
|
||||
|
||||
// alternative merge options
|
||||
const crawlersAndCLIsParser2 = new UAParser([Crawlers, CLIs]);
|
||||
const crawlersAndCLIsParser3 = new UAParser(facebookBot, [Crawlers, CLIs]);
|
||||
assert.deepEqual(crawlersAndCLIsParser2.setUA(wget).getBrowser(), {name: "Wget", version: "1.21.1", major: "1", type:"cli"});
|
||||
assert.deepEqual(crawlersAndCLIsParser3.getBrowser(), {name: "FacebookBot", version: "1.0", major: "1", type:"crawler"});
|
||||
assert.deepEqual(crawlersAndCLIsParser2.setUA(wget).getBrowser(), {name: CLI.WGET, version: "1.21.1", major: "1", type: BrowserType.CLI});
|
||||
assert.deepEqual(crawlersAndCLIsParser3.getBrowser(), {name: Crawler.META_FACEBOOKBOT, version: "1.0", major: "1", type: BrowserType.CRAWLER});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ const assert = require('assert');
|
||||
const { UAParser } = require('../../src/main/ua-parser');
|
||||
const { getDeviceVendor, isAppleSilicon, isAIBot, isBot, isChromeFamily } = require('../../src/helpers/ua-parser-helpers');
|
||||
const { Bots, Emails } = require('../../src/extensions/ua-parser-extensions');
|
||||
const { DeviceVendor } = require('../../src/enums/ua-parser-enums');
|
||||
|
||||
describe('getDeviceVendor', () => {
|
||||
it('Can guess the device vendor from a model name', () => {
|
||||
@@ -11,10 +12,10 @@ describe('getDeviceVendor', () => {
|
||||
const modelNexus = 'Nexus 6P';
|
||||
const modelAquos = 'AQUOS-TVX19B';
|
||||
|
||||
assert.equal(getDeviceVendor(modelSM), 'Samsung');
|
||||
assert.equal(getDeviceVendor(modelRedmi), 'Xiaomi');
|
||||
assert.equal(getDeviceVendor(modelNexus), 'Huawei');
|
||||
assert.equal(getDeviceVendor(modelAquos), 'Sharp');
|
||||
assert.equal(getDeviceVendor(modelSM), DeviceVendor.SAMSUNG);
|
||||
assert.equal(getDeviceVendor(modelRedmi), DeviceVendor.XIAOMI);
|
||||
assert.equal(getDeviceVendor(modelNexus), DeviceVendor.HUAWEI);
|
||||
assert.equal(getDeviceVendor(modelAquos), DeviceVendor.SHARP);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ var cpus = require('../data/ua/cpu/cpu-all.json');
|
||||
var devices = readJsonFiles('test/data/ua/device');
|
||||
var engines = require('../data/ua/engine/engine-all.json');
|
||||
var os = readJsonFiles('test/data/ua/os');
|
||||
var { Headers } = require('node-fetch');
|
||||
|
||||
function readJsonFiles(dir) {
|
||||
var list = [];
|
||||
@@ -91,6 +90,34 @@ describe('Returns', function () {
|
||||
});
|
||||
done();
|
||||
});
|
||||
|
||||
it('works even when Array.prototype has been mangled', function(done) {
|
||||
const result = withMangledArrayProto(() => new UAParser('').getResult());
|
||||
|
||||
function withMangledArrayProto(fn, key = 'isEmpty', value = function() { return this.length === 0; }) {
|
||||
const originalValue = Array.prototype[key];
|
||||
const restore = Object.hasOwnProperty.call(Array.prototype, key)
|
||||
? () => Array.prototype[key] = originalValue
|
||||
: () => delete Array.prototype[key];
|
||||
|
||||
Array.prototype[key] = value;
|
||||
const result = fn();
|
||||
restore();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
assert.deepEqual(result,
|
||||
{
|
||||
ua : '',
|
||||
browser: { name: undefined, version: undefined, major: undefined, type: undefined },
|
||||
cpu: { architecture: undefined },
|
||||
device: { vendor: undefined, model: undefined, type: undefined },
|
||||
engine: { name: undefined, version: undefined},
|
||||
os: { name: undefined, version: undefined }
|
||||
});
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Extending Regex', function () {
|
||||
@@ -135,6 +162,14 @@ describe('Extending Regex', function () {
|
||||
assert.deepEqual(myParser3.setUA(myUA2).getDevice(), {vendor: "MyTab", model: "14 Pro Max", type: "tablet"});
|
||||
});
|
||||
|
||||
describe('User-agent with trailing space', function () {
|
||||
it ('trailing space will be trimmed', function () {
|
||||
const uastring = ' Opera/9.21 (Windows NT 5.1; U; ru) ';
|
||||
const { ua } = UAParser(uastring);
|
||||
assert.equal(ua, 'Opera/9.21 (Windows NT 5.1; U; ru) ');
|
||||
});
|
||||
});
|
||||
|
||||
describe('User-agent length', function () {
|
||||
var UA_MAX_LENGTH = 500;
|
||||
|
||||
@@ -347,10 +382,27 @@ describe('Read user-agent data from req.headers', function () {
|
||||
assert.strictEqual(engine.name, "EdgeHTML");
|
||||
});
|
||||
|
||||
it('Fetch API\'s Header can be passed directly into headers', () => {
|
||||
const reqHeaders = new Headers();
|
||||
reqHeaders.append('User-Agent', 'Midori/0.2.2 (X11; Linux i686; U; en-us) WebKit/531.2+');
|
||||
const { browser } = UAParser(reqHeaders);
|
||||
assert.strictEqual(browser.is('Midori'), true);
|
||||
// Headers supported in node 18+ - https://developer.mozilla.org/en-US/docs/Web/API/Headers
|
||||
if (typeof Headers !== 'undefined') {
|
||||
it('Fetch API\'s Header can be passed directly into headers', () => {
|
||||
const reqHeaders = new Headers();
|
||||
reqHeaders.append('User-Agent', 'Midori/0.2.2 (X11; Linux i686; U; en-us) WebKit/531.2+');
|
||||
const { browser } = UAParser(reqHeaders);
|
||||
assert.strictEqual(browser.is('Midori'), true);
|
||||
});
|
||||
}
|
||||
|
||||
it('Headers field name should be case insensitive', function () {
|
||||
const hEaDeRs = {
|
||||
'uSeR-aGenT' : 'Midori/0.2.2 (X11; Linux i686; U; en-us) WebKit/531.2+'
|
||||
};
|
||||
const { browser } = UAParser(hEaDeRs);
|
||||
assert.strictEqual(browser.toString(), "Midori 0.2.2");
|
||||
});
|
||||
});
|
||||
|
||||
it('Empty headers should not raise any error', function () {
|
||||
const emptyHeaders = {};
|
||||
const { browser } = UAParser(emptyHeaders);
|
||||
assert.strictEqual(browser.toString(), "undefined");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
const assert = require('assert');
|
||||
const { UAParser } = require('../../src/main/ua-parser');
|
||||
const { BrowserName, CPUArch, DeviceType, DeviceVendor, EngineName, OSName } = require('../../src/enums/ua-parser-enums');
|
||||
const UACHTests = require('../data/ua-ch/headers');
|
||||
|
||||
describe('Map UA-CH headers', () => {
|
||||
|
||||
@@ -25,27 +27,27 @@ describe('Map UA-CH headers', () => {
|
||||
it('Can read from client-hints headers using `withClientHints()`', () => {
|
||||
|
||||
assert.strictEqual(uap.ua, "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36");
|
||||
assert.strictEqual(uap.browser.name, "Chrome");
|
||||
assert.strictEqual(uap.browser.name, BrowserName.CHROME);
|
||||
assert.strictEqual(uap.browser.version, "93.0.1.2");
|
||||
assert.strictEqual(uap.browser.major, "93");
|
||||
assert.strictEqual(browser.name, "Chrome");
|
||||
assert.strictEqual(browser.name, BrowserName.CHROME);
|
||||
assert.strictEqual(browser.version, "93.0.1.2");
|
||||
assert.strictEqual(browser.major, "93");
|
||||
assert.strictEqual(uap.cpu.architecture, "arm64");
|
||||
assert.strictEqual(cpu.architecture, "arm64");
|
||||
assert.strictEqual(uap.device.type, "mobile");
|
||||
assert.strictEqual(uap.cpu.architecture, CPUArch.ARM_64);
|
||||
assert.strictEqual(cpu.architecture, CPUArch.ARM_64);
|
||||
assert.strictEqual(uap.device.type, DeviceType.MOBILE);
|
||||
assert.strictEqual(uap.device.model, "Pixel 99");
|
||||
assert.strictEqual(uap.device.vendor, "Google");
|
||||
assert.strictEqual(device.type, "mobile");
|
||||
assert.strictEqual(uap.device.vendor, DeviceVendor.GOOGLE);
|
||||
assert.strictEqual(device.type, DeviceType.MOBILE);
|
||||
assert.strictEqual(device.model, "Pixel 99");
|
||||
assert.strictEqual(device.vendor, "Google");
|
||||
assert.strictEqual(uap.engine.name, 'Blink');
|
||||
assert.strictEqual(device.vendor, DeviceVendor.GOOGLE);
|
||||
assert.strictEqual(uap.engine.name, EngineName.BLINK);
|
||||
assert.strictEqual(uap.engine.version, '93.0.1.2');
|
||||
assert.strictEqual(engine.name, 'Blink');
|
||||
assert.strictEqual(engine.name, EngineName.BLINK);
|
||||
assert.strictEqual(engine.version, '93.0.1.2');
|
||||
assert.strictEqual(uap.os.name, "Windows");
|
||||
assert.strictEqual(uap.os.name, OSName.WINDOWS);
|
||||
assert.strictEqual(uap.os.version, "11");
|
||||
assert.strictEqual(os.name, "Windows");
|
||||
assert.strictEqual(os.name, OSName.WINDOWS);
|
||||
assert.strictEqual(os.version, "11");
|
||||
});
|
||||
|
||||
@@ -58,16 +60,16 @@ describe('Map UA-CH headers', () => {
|
||||
engine = new UAParser(headers).getEngine();
|
||||
os = new UAParser(headers).getOS();
|
||||
|
||||
assert.strictEqual(uap.browser.name, "Chrome");
|
||||
assert.strictEqual(uap.browser.name, BrowserName.CHROME);
|
||||
assert.strictEqual(uap.browser.version, "110.0.0.0");
|
||||
assert.strictEqual(uap.browser.major, "110");
|
||||
assert.strictEqual(uap.cpu.architecture, "amd64");
|
||||
assert.strictEqual(uap.cpu.architecture, CPUArch.X86_64);
|
||||
assert.strictEqual(uap.device.type, undefined);
|
||||
assert.strictEqual(uap.device.model, undefined);
|
||||
assert.strictEqual(uap.device.vendor, undefined);
|
||||
assert.strictEqual(uap.engine.name, 'Blink');
|
||||
assert.strictEqual(uap.engine.name, EngineName.BLINK);
|
||||
assert.strictEqual(uap.engine.version, '110.0.0.0');
|
||||
assert.strictEqual(uap.os.name, "Linux");
|
||||
assert.strictEqual(uap.os.name, OSName.LINUX);
|
||||
assert.strictEqual(uap.os.version, undefined);
|
||||
});
|
||||
|
||||
@@ -80,16 +82,16 @@ describe('Map UA-CH headers', () => {
|
||||
|
||||
uap = UAParser(headers2).withClientHints();
|
||||
|
||||
assert.strictEqual(uap.browser.name, "Chrome");
|
||||
assert.strictEqual(uap.browser.name, BrowserName.CHROME);
|
||||
assert.strictEqual(uap.browser.version, "110.0.0.0");
|
||||
assert.strictEqual(uap.browser.major, "110");
|
||||
assert.strictEqual(uap.cpu.architecture, "amd64");
|
||||
assert.strictEqual(uap.device.type, "mobile");
|
||||
assert.strictEqual(uap.cpu.architecture, CPUArch.X86_64);
|
||||
assert.strictEqual(uap.device.type, DeviceType.MOBILE);
|
||||
assert.strictEqual(uap.device.model, undefined);
|
||||
assert.strictEqual(uap.device.vendor, undefined);
|
||||
assert.strictEqual(uap.engine.name, 'Blink');
|
||||
assert.strictEqual(uap.engine.name, EngineName.BLINK);
|
||||
assert.strictEqual(uap.engine.version, '110.0.0.0');
|
||||
assert.strictEqual(uap.os.name, "Linux");
|
||||
assert.strictEqual(uap.os.name, OSName.LINUX);
|
||||
assert.strictEqual(uap.os.version, undefined);
|
||||
});
|
||||
|
||||
@@ -116,10 +118,10 @@ describe('Map UA-CH headers', () => {
|
||||
}
|
||||
*/
|
||||
|
||||
assert.strictEqual(ua.os.is("macOS"), true);
|
||||
assert.strictEqual(ua.cpu.is("arm"), true);
|
||||
assert.strictEqual(ua.device.is("mobile"), false);
|
||||
assert.strictEqual(ua.device.is("tablet"), false);
|
||||
assert.strictEqual(ua.os.is(OSName.MACOS), true);
|
||||
assert.strictEqual(ua.cpu.is(CPUArch.ARM), true);
|
||||
assert.strictEqual(ua.device.is(DeviceType.MOBILE), false);
|
||||
assert.strictEqual(ua.device.is(DeviceType.TABLET), false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -138,11 +140,11 @@ describe('Map UA-CH headers', () => {
|
||||
};
|
||||
|
||||
UAParser(FFVR).withClientHints().then(ua => {
|
||||
assert.strictEqual(ua.device.type, 'xr');
|
||||
assert.strictEqual(ua.device.type, DeviceType.XR);
|
||||
});
|
||||
|
||||
UAParser(FFEInk).withClientHints().then(ua => {
|
||||
assert.strictEqual(ua.device.type, 'tablet');
|
||||
assert.strictEqual(ua.device.type, DeviceType.TABLET);
|
||||
});
|
||||
|
||||
|
||||
@@ -168,7 +170,7 @@ describe('Map UA-CH headers', () => {
|
||||
|
||||
uap = UAParser(headers2).withClientHints();
|
||||
|
||||
assert.strictEqual(uap.browser.name, "Chrome");
|
||||
assert.strictEqual(uap.browser.name, BrowserName.CHROME);
|
||||
assert.strictEqual(uap.browser.version, undefined);
|
||||
assert.strictEqual(uap.browser.major, undefined);
|
||||
});
|
||||
@@ -195,258 +197,37 @@ describe('Map UA-CH headers', () => {
|
||||
};
|
||||
|
||||
uap = UAParser(headers3a).withClientHints();
|
||||
assert.strictEqual(uap.browser.name, "Chrome");
|
||||
assert.strictEqual(uap.browser.name, BrowserName.CHROME);
|
||||
assert.strictEqual(uap.browser.version, "120.0.6099.132");
|
||||
|
||||
uap = UAParser(headers3b).withClientHints();
|
||||
assert.strictEqual(uap.browser.name, "Chrome");
|
||||
assert.strictEqual(uap.browser.name, BrowserName.CHROME);
|
||||
assert.strictEqual(uap.browser.version, "120.0.6099.132");
|
||||
|
||||
uap = UAParser(headers3c).withClientHints();
|
||||
assert.strictEqual(uap.browser.name, "Chrome");
|
||||
assert.strictEqual(uap.browser.name, BrowserName.CHROME);
|
||||
assert.strictEqual(uap.browser.version, "120.0.6099.132");
|
||||
|
||||
uap = UAParser(headers3d).withClientHints();
|
||||
assert.strictEqual(uap.browser.name, "Edge");
|
||||
assert.strictEqual(uap.browser.name, BrowserName.EDGE);
|
||||
assert.strictEqual(uap.browser.version, "120.0.6099.133");
|
||||
|
||||
uap = UAParser(headers3e).withClientHints();
|
||||
assert.strictEqual(uap.browser.name, "Edge");
|
||||
assert.strictEqual(uap.browser.name, BrowserName.EDGE);
|
||||
assert.strictEqual(uap.browser.version, "120.0.6099.133");
|
||||
|
||||
uap = UAParser(headers3f).withClientHints();
|
||||
assert.strictEqual(uap.browser.name, "Edge");
|
||||
assert.strictEqual(uap.browser.name, BrowserName.EDGE);
|
||||
assert.strictEqual(uap.browser.version, "120.0.6099.133");
|
||||
});
|
||||
});
|
||||
|
||||
describe('UA-CH Headers tests', () => {
|
||||
[
|
||||
{
|
||||
headers : {
|
||||
'sec-ch-ua': '"Avast Secure Browser";v="131", "Chromium";v="131", "Not_A Brand";v="24"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Avast Secure Browser',
|
||||
version : '131',
|
||||
major : '131',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
headers : {
|
||||
'sec-ch-ua': '"Not A(Brand";v="8", "Chromium";v="132", "Brave";v="132"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Brave',
|
||||
version : '132',
|
||||
major : '132',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
headers : {
|
||||
'sec-ch-ua': '"Google Chrome";v="111", "Not(A:Brand";v="8", "Chromium";v="111"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Chrome',
|
||||
version : '111',
|
||||
major : '111',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
headers : {
|
||||
'sec-ch-ua': '"Chromium";v="124", "HeadlessChrome";v="124", "Not-A.Brand";v="99"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Chrome Headless',
|
||||
version : '124',
|
||||
major : '124',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
headers : {
|
||||
'sec-ch-ua': '"Android WebView";v="123", "Not:A-Brand";v="8", "Chromium";v="123"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Chrome WebView',
|
||||
version : '123',
|
||||
major : '123',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
headers : {
|
||||
'sec-ch-ua': '"DuckDuckGo";v="131", "Chromium";v="131", "Not_A Brand";v="24"'
|
||||
},
|
||||
expect : {
|
||||
browser : {
|
||||
name : 'DuckDuckGo',
|
||||
version : '131',
|
||||
major : '131',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
headers : {
|
||||
'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Edge',
|
||||
version : '120',
|
||||
major : '120',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
headers : {
|
||||
'sec-ch-ua': '" Not;A Brand";v="99", "Microsoft Edge";v="103", "Chromium";v="103", "Microsoft Edge WebView2";v="104"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Edge WebView2',
|
||||
version : '104',
|
||||
major : '104',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
headers : {
|
||||
'sec-ch-ua': '"Not.A/Brand";v="8", "Chromium";v="114", "HuaweiBrowser";v="114"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Huawei Browser',
|
||||
version : '114',
|
||||
major : '114',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
headers : {
|
||||
'sec-ch-ua': '"Miui Browser";v="123", "Not:A-Brand";v="8", "Chromium";v="123"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'MIUI Browser',
|
||||
version : '123',
|
||||
major : '123',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
headers : {
|
||||
'sec-ch-ua': '"Chromium";v="130", "Oculus Browser";v="36", "Not?A_Brand";v="99"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Oculus Browser',
|
||||
version : '36',
|
||||
major : '36',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
headers : {
|
||||
'sec-ch-ua': '"Opera";v="116", "Chromium";v="131", "Not_A Brand";v="24"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Opera',
|
||||
version : '116',
|
||||
major : '116',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
headers : {
|
||||
'sec-ch-ua': '"Chromium";v="128", "Not;A=Brand";v="24", "Opera GX";v="114"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Opera GX',
|
||||
version : '114',
|
||||
major : '114',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
headers : {
|
||||
'sec-ch-ua': '"OperaMobile";v="86", ";Not A Brand";v="99", "Opera";v="115", "Chromium";v="130"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Opera Mobi',
|
||||
version : '86',
|
||||
major : '86',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
headers : {
|
||||
'sec-ch-ua': '"Chromium";v="132", "OperaMobile";v="87", "Opera";v="117", " Not A;Brand";v="99"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Opera Mobi',
|
||||
version : '87',
|
||||
major : '87',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
headers : {
|
||||
'sec-ch-ua': '"Chromium";v="125", "Not.A/Brand";v="24", "Samsung Internet";v="27.0"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Samsung Internet',
|
||||
version : '27.0',
|
||||
major : '27',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
headers : {
|
||||
'sec-ch-ua': '"Chromium";v="130", "YaBrowser";v="24.12", "Not?A_Brand";v="99", "Yowser";v="2.5"'
|
||||
},
|
||||
expect: {
|
||||
browser : {
|
||||
name : 'Yandex',
|
||||
version : '24.12',
|
||||
major : '24',
|
||||
type : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
.forEach(test => {
|
||||
const { browser } = UAParser(test.headers).withClientHints();
|
||||
assert.deepEqual(browser, test.expect.browser);
|
||||
UACHTests.forEach(test => {
|
||||
it(`Test for ${test.desc}`, () => {
|
||||
const { browser } = UAParser(test.headers).withClientHints();
|
||||
assert.deepEqual(browser, test.expect.browser);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -455,169 +236,169 @@ describe('Identify vendor & type of device from given model name', () => {
|
||||
{
|
||||
model: '220733SG',
|
||||
expect: {
|
||||
vendor : 'Xiaomi',
|
||||
type : 'mobile'
|
||||
vendor : DeviceVendor.XIAOMI,
|
||||
type : DeviceType.MOBILE
|
||||
}
|
||||
},
|
||||
{
|
||||
model: '5087Z',
|
||||
expect: {
|
||||
vendor : 'TCL',
|
||||
type : 'mobile'
|
||||
vendor : DeviceVendor.TCL,
|
||||
type : DeviceType.MOBILE
|
||||
}
|
||||
},
|
||||
{
|
||||
model: '9137W',
|
||||
expect: {
|
||||
vendor : 'TCL',
|
||||
type : 'tablet'
|
||||
vendor : DeviceVendor.TCL,
|
||||
type : DeviceType.TABLET
|
||||
}
|
||||
},
|
||||
{
|
||||
model: 'BE2015',
|
||||
expect: {
|
||||
vendor : 'OnePlus',
|
||||
type : 'mobile'
|
||||
vendor : DeviceVendor.ONEPLUS,
|
||||
type : DeviceType.MOBILE
|
||||
}
|
||||
},
|
||||
{
|
||||
model: 'CPH2389',
|
||||
expect: {
|
||||
vendor : 'OnePlus',
|
||||
type : 'mobile'
|
||||
vendor : DeviceVendor.ONEPLUS,
|
||||
type : DeviceType.MOBILE
|
||||
}
|
||||
},
|
||||
{
|
||||
model: 'Infinix X669C',
|
||||
expect: {
|
||||
vendor : 'Infinix',
|
||||
type : 'mobile'
|
||||
vendor : DeviceVendor.INFINIX,
|
||||
type : DeviceType.MOBILE
|
||||
}
|
||||
},
|
||||
{
|
||||
model: 'itel L6502',
|
||||
expect: {
|
||||
vendor : 'itel',
|
||||
type : 'mobile'
|
||||
vendor : DeviceVendor.ITEL,
|
||||
type : DeviceType.MOBILE
|
||||
}
|
||||
},
|
||||
{
|
||||
model: 'Lenovo TB-X606F',
|
||||
expect: {
|
||||
vendor : 'Lenovo',
|
||||
type : 'tablet'
|
||||
vendor : DeviceVendor.LENOVO,
|
||||
type : DeviceType.TABLET
|
||||
}
|
||||
},
|
||||
{
|
||||
model: 'LM-Q720',
|
||||
expect: {
|
||||
vendor : 'LG',
|
||||
type : 'mobile'
|
||||
vendor : DeviceVendor.LG,
|
||||
type : DeviceType.MOBILE
|
||||
}
|
||||
},
|
||||
{
|
||||
model: 'M2003J15SC',
|
||||
expect: {
|
||||
vendor : 'Xiaomi',
|
||||
type : 'mobile'
|
||||
vendor : DeviceVendor.XIAOMI,
|
||||
type : DeviceType.MOBILE
|
||||
}
|
||||
},
|
||||
{
|
||||
model: 'MAR-LX1A',
|
||||
expect: {
|
||||
vendor : 'Huawei',
|
||||
type : 'mobile'
|
||||
vendor : DeviceVendor.HUAWEI,
|
||||
type : DeviceType.MOBILE
|
||||
}
|
||||
},
|
||||
{
|
||||
model: 'moto g(20)',
|
||||
expect: {
|
||||
vendor : 'Motorola',
|
||||
type : 'mobile'
|
||||
vendor : DeviceVendor.MOTOROLA,
|
||||
type : DeviceType.MOBILE
|
||||
}
|
||||
},
|
||||
{
|
||||
model: 'Nokia C210',
|
||||
expect: {
|
||||
vendor : 'Nokia',
|
||||
type : 'mobile'
|
||||
vendor : DeviceVendor.NOKIA,
|
||||
type : DeviceType.MOBILE
|
||||
}
|
||||
},
|
||||
{
|
||||
model: 'Pixel 8',
|
||||
expect: {
|
||||
vendor : 'Google',
|
||||
type : 'mobile'
|
||||
vendor : DeviceVendor.GOOGLE,
|
||||
type : DeviceType.MOBILE
|
||||
}
|
||||
},
|
||||
{
|
||||
model: 'Redmi Note 9S',
|
||||
expect: {
|
||||
vendor : 'Xiaomi',
|
||||
type : 'mobile'
|
||||
vendor : DeviceVendor.XIAOMI,
|
||||
type : DeviceType.MOBILE
|
||||
}
|
||||
},
|
||||
{
|
||||
model: 'RMX3830',
|
||||
expect: {
|
||||
vendor : 'Realme',
|
||||
type : 'mobile'
|
||||
vendor : DeviceVendor.REALME,
|
||||
type : DeviceType.MOBILE
|
||||
}
|
||||
},
|
||||
{
|
||||
model: 'SM-S536DL',
|
||||
expect: {
|
||||
vendor : 'Samsung',
|
||||
type : 'mobile'
|
||||
vendor : DeviceVendor.SAMSUNG,
|
||||
type : DeviceType.MOBILE
|
||||
}
|
||||
},
|
||||
{
|
||||
model: 'SM-S546VL',
|
||||
expect: {
|
||||
vendor : 'Samsung',
|
||||
type : 'mobile'
|
||||
vendor : DeviceVendor.SAMSUNG,
|
||||
type : DeviceType.MOBILE
|
||||
}
|
||||
},
|
||||
{
|
||||
model: 'SM-T875',
|
||||
expect: {
|
||||
vendor : 'Samsung',
|
||||
type : 'tablet'
|
||||
vendor : DeviceVendor.SAMSUNG,
|
||||
type : DeviceType.TABLET
|
||||
}
|
||||
},
|
||||
{
|
||||
model: 'STK-L21',
|
||||
expect: {
|
||||
vendor : 'Huawei',
|
||||
type : 'mobile'
|
||||
vendor : DeviceVendor.HUAWEI,
|
||||
type : DeviceType.MOBILE
|
||||
}
|
||||
},
|
||||
{
|
||||
model: 'T430W',
|
||||
expect: {
|
||||
vendor : 'TCL',
|
||||
type : 'mobile'
|
||||
vendor : DeviceVendor.TCL,
|
||||
type : DeviceType.MOBILE
|
||||
}
|
||||
},
|
||||
{
|
||||
model: 'TECNO KI5k',
|
||||
expect: {
|
||||
vendor : 'TECNO',
|
||||
type : 'mobile'
|
||||
vendor : DeviceVendor.TECNO,
|
||||
type : DeviceType.MOBILE
|
||||
}
|
||||
},
|
||||
{
|
||||
model: 'vivo 1820',
|
||||
expect: {
|
||||
vendor : 'Vivo',
|
||||
type : 'mobile'
|
||||
vendor : DeviceVendor.VIVO,
|
||||
type : DeviceType.MOBILE
|
||||
}
|
||||
},
|
||||
{
|
||||
model: 'Xbox',
|
||||
expect: {
|
||||
vendor : 'Microsoft',
|
||||
type : 'console'
|
||||
vendor : DeviceVendor.MICROSOFT,
|
||||
type : DeviceType.CONSOLE
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user