mirror of
https://github.com/faisalman/ua-parser-js.git
synced 2025-11-15 22:52:16 +03:00
Compare commits
55 Commits
2.0.4-pro-
...
pro-person
| 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 | ||
|
|
4e8c13cbb4 | ||
|
|
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 | ||
|
|
6ea2df63dc | ||
|
|
db06606acd |
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
|
||||
|
||||
20
LICENSE.md
20
LICENSE.md
@@ -1,4 +1,4 @@
|
||||
# UAPARSER.JS PRO ENTERPRISE LICENSE
|
||||
# UAPARSER.JS PRO PERSONAL LICENSE
|
||||
|
||||
Version 2, July 2024
|
||||
|
||||
@@ -10,7 +10,7 @@ Copyright (C) 2023-2024 Faisal Salman <f+ua-parser-js@faisalman.com>
|
||||
|
||||
"We" are the team behind UAParser.js.
|
||||
|
||||
"You" are the individual, organization, or company who is responsible for purchasing this license.
|
||||
"You" are the individual who is responsible for purchasing this license.
|
||||
|
||||
"The Code" is UAParser.js.
|
||||
|
||||
@@ -24,25 +24,27 @@ We retain all title, intellectual property, and ownership rights to The Code.
|
||||
|
||||
The Code is licensed, not sold, to You for use solely subject to the terms and conditions detailed here.
|
||||
|
||||
We grant You (and only You) a limited, non-exclusive, non-transferable, non-sublicensable, royalty-free right to use, copy, and modify The Code.
|
||||
We grant You (and only You) a personal, limited, non-exclusive, non-transferable, non-sublicensable, royalty-free right to use, copy, and modify The Code.
|
||||
|
||||
This license is only valid for You as one (1) individual, organization, or company and cannot be transferred to another individual, organization, or company.
|
||||
This license is only valid for You as one (1) individual and cannot be transferred to another individual or organization.
|
||||
|
||||
---
|
||||
|
||||
## Rights
|
||||
|
||||
You may use, copy, and modify The Code for an indefinite number of Projects.
|
||||
You may use and modify The Code to create as many personal, hobby, educational, and other non-profit projects as you want for yourself.
|
||||
|
||||
You have the right to receive lifetime updates and one (1) year of support, starting from the time you make the purchase.
|
||||
You may create any number of copies of The Code for yourself.
|
||||
|
||||
You have the right to get lifetime updates and one (1) year of support, starting from the time you make the purchase.
|
||||
|
||||
---
|
||||
|
||||
## Restrictions
|
||||
|
||||
You may not redistribute The Code, as-is or modified, except as a part of a Project that you made.
|
||||
You may not use or modify The Code in such a way that it may be used directly for commercial purposes.
|
||||
|
||||
If You transfer a Project to a client, the use of The Code must be limited to the original functionality that You created for them. The Code must not be extracted, reproduced, or used in any other way. You must inform your client of this condition.
|
||||
You may not redistribute The Code, as-is or modified, except as a part of a Project that you made for yourself.
|
||||
|
||||
You may not deliver a Project that contains The Code as an open-source Project that might be used for commercial purposes by the general public, except with our written consent.
|
||||
|
||||
@@ -52,7 +54,7 @@ You may not use The Code for unlawful, inappropriate, illegal, or offensive purp
|
||||
|
||||
## Limitations
|
||||
|
||||
The Code is provided 'as is' without warranty of any kind, expressed or implied.
|
||||
The Code is provided 'as is' without warranty of any kind, expressed or implied.
|
||||
|
||||
We shall not be liable for any damages, including but not limited to, direct, indirect, special, incidental, or consequential damages or losses that occur by the use of The Code.
|
||||
|
||||
|
||||
17
README.md
17
README.md
@@ -1,6 +1,6 @@
|
||||
# UAParser.js PRO Enterprise License
|
||||
# UAParser.js PRO Personal License
|
||||
|
||||
Thank you for choosing the UAParser.js PRO Enterprise License.
|
||||
Thank you for choosing the UAParser.js PRO Personal License.
|
||||
|
||||
Please be aware that using this package without a valid license purchase is strictly prohibited and constitutes a violation of applicable copyright laws.
|
||||
|
||||
@@ -11,20 +11,23 @@ If you have not yet purchased a license, you may do so at https://store.faisalma
|
||||
# Download
|
||||
|
||||
```sh
|
||||
npm install @ua-parser-js/pro-enterprise
|
||||
npm install @ua-parser-js/pro-personal
|
||||
```
|
||||
|
||||
|
||||
# Documentation
|
||||
|
||||
https://docs.uaparser.dev
|
||||
|
||||
```js
|
||||
import { UAParser } from '@ua-parser-js/pro-enterprise';
|
||||
import { UAParser } from '@ua-parser-js/pro-personal';
|
||||
```
|
||||
|
||||
```js
|
||||
import { isFrozenUA } from '@ua-parser-js/pro-personal/helpers';
|
||||
```
|
||||
|
||||
# License
|
||||
|
||||
UAParser.js PRO Enterprise
|
||||
UAParser.js PRO Personal
|
||||
|
||||
Copyright (c) 2023-2024 Faisal Salman <<f@faisalman.com>>
|
||||
Copyright (c) 2023-2025 Faisal Salman <<f@faisalman.com>>
|
||||
|
||||
6
dist/ua-parser.min.js
vendored
6
dist/ua-parser.min.js
vendored
File diff suppressed because one or more lines are too long
6
dist/ua-parser.min.mjs
vendored
6
dist/ua-parser.min.mjs
vendored
File diff suppressed because one or more lines are too long
6
dist/ua-parser.pack.js
vendored
6
dist/ua-parser.pack.js
vendored
File diff suppressed because one or more lines are too long
6
dist/ua-parser.pack.mjs
vendored
6
dist/ua-parser.pack.mjs
vendored
File diff suppressed because one or more lines are too long
156
package-lock.json
generated
156
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@ua-parser-js/pro-enterprise",
|
||||
"version": "2.0.4",
|
||||
"name": "@ua-parser-js/pro-personal",
|
||||
"version": "2.0.6",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ua-parser-js/pro-enterprise",
|
||||
"version": "2.0.4",
|
||||
"name": "@ua-parser-js/pro-personal",
|
||||
"version": "2.0.6",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@@ -23,14 +23,12 @@
|
||||
],
|
||||
"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": {
|
||||
"pro-enterprise": "script/cli.js"
|
||||
"pro-personal": "script/cli.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/parser": "7.15.8",
|
||||
@@ -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,25 +968,26 @@
|
||||
"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",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
|
||||
"integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
@@ -1577,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",
|
||||
@@ -1949,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",
|
||||
@@ -2151,6 +2071,20 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/playwright/node_modules/fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/plur": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/plur/-/plur-4.0.0.tgz",
|
||||
@@ -2685,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",
|
||||
@@ -2763,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",
|
||||
@@ -2778,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",
|
||||
|
||||
20
package.json
20
package.json
@@ -1,25 +1,25 @@
|
||||
{
|
||||
"title": "UAParser.js PRO Enterprise",
|
||||
"name": "@ua-parser-js/pro-enterprise",
|
||||
"version": "2.0.4",
|
||||
"title": "UAParser.js PRO Personal",
|
||||
"name": "@ua-parser-js/pro-personal",
|
||||
"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,13 +1,13 @@
|
||||
///////////////////////////////////////////////
|
||||
/* 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 Enterprise License */
|
||||
UAParser.js PRO Personal License */
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/*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,15 +3,15 @@
|
||||
// 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 Enterprise License */
|
||||
UAParser.js PRO Personal License */
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/*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,8 +1,8 @@
|
||||
///////////////////////////////////////////////
|
||||
/* 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 Enterprise License */
|
||||
UAParser.js PRO Personal License */
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/*jshint esversion: 6 */
|
||||
@@ -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,10 +3,10 @@
|
||||
// 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 Enterprise License */
|
||||
UAParser.js PRO Personal License */
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/*jshint esversion: 6 */
|
||||
@@ -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,18 +1,19 @@
|
||||
///////////////////////////////////////////////
|
||||
/* 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 Enterprise License */
|
||||
UAParser.js PRO Personal License */
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/*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,20 +3,21 @@
|
||||
// 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 Enterprise License */
|
||||
UAParser.js PRO Personal License */
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/*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,7 +1,7 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/* UAParser.js v2.0.4
|
||||
/* UAParser.js v2.0.6
|
||||
Copyright © 2012-2025 Faisal Salman <f@faisalman.com>
|
||||
UAParser.js PRO Enterprise License *//*
|
||||
UAParser.js PRO Personal License *//*
|
||||
Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.
|
||||
Supports browser & node.js environment.
|
||||
Demo : https://uaparser.dev
|
||||
@@ -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,9 +3,9 @@
|
||||
// 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 Enterprise License *//*
|
||||
UAParser.js PRO Personal License *//*
|
||||
Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.
|
||||
Supports browser & node.js environment.
|
||||
Demo : https://uaparser.dev
|
||||
@@ -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