Compare commits

..

1 Commits

24 changed files with 331 additions and 798 deletions

View File

@ -65,35 +65,6 @@
--- ---
## 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 ## Version 2.0.4
- Add new browser: Edge WebView, Edge WebView2 - Add new browser: Edge WebView, Edge WebView2
@ -269,16 +240,6 @@
--- ---
## 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 ## Version 0.7.40 / 1.0.40
- Add new browser: 115, LibreWolf, Slimboat, Slimjet - Add new browser: 115, LibreWolf, Slimboat, Slimjet
- Add new device: Advan, Cat, Energizer, IMO, Micromax, Smartfren - Add new device: Advan, Cat, Energizer, IMO, Micromax, Smartfren

View File

@ -12,12 +12,13 @@
<a href="https://www.npmjs.com/package/ua-parser-js"><img src="https://img.shields.io/npm/v/ua-parser-js.svg?logo=npm&color=red&style=for-the-badge"></a> <a href="https://www.npmjs.com/package/ua-parser-js"><img src="https://img.shields.io/npm/v/ua-parser-js.svg?logo=npm&color=red&style=for-the-badge"></a>
<a href="https://cdnjs.com/libraries/UAParser.js"><img src="https://img.shields.io/cdnjs/v/UAParser.js.svg?color=orange&style=for-the-badge"></a> <a href="https://cdnjs.com/libraries/UAParser.js"><img src="https://img.shields.io/cdnjs/v/UAParser.js.svg?color=orange&style=for-the-badge"></a>
<img src="https://img.shields.io/ossf-scorecard/github.com/faisalman/ua-parser-js?label=openssf%20scorecard&style=for-the-badge"> <img src="https://img.shields.io/ossf-scorecard/github.com/faisalman/ua-parser-js?label=openssf%20scorecard&style=for-the-badge">
<a target="_blank" href="https://discord.gg/stt86vmr"><img alt="Discord invite" src="https://dcbadge.limes.pink/api/server/https://discord.gg/stt86vmr"></a>
</p> </p>
# UAParser.js # UAParser.js
The most comprehensive, compact, and up-to-date JavaScript library to detect user's browser, OS, CPU, and device type/model. Also detect bots, apps, and more. Runs seamlessly in the browser (client-side) or Node.js (server-side). The most comprehensive, compact, & up-to-date isomorphic JavaScript library to detect
user's Browser, Engine, OS, CPU, and Device type/model. Runs either in browser
(client-side) or node.js (server-side).
# Demo # Demo
@ -32,7 +33,7 @@ The most comprehensive, compact, and up-to-date JavaScript library to detect use
Before upgrading from `v0.7` / `v1.0`, please read [CHANGELOG](CHANGELOG.md) to Before upgrading from `v0.7` / `v1.0`, please read [CHANGELOG](CHANGELOG.md) to
see what's new & breaking. see what's new & breaking.
# Package & Pricing # License Options
<table> <table>
<thead> <thead>
@ -45,8 +46,8 @@ see what's new & breaking.
<tbody> <tbody>
<tr> <tr>
<td>License options</td> <td>License options</td>
<td>MIT (v1.x)</td> <td>MIT (v0.7~v1.0)</td>
<td>AGPL (v2.x)</td> <td>AGPL (&gt;=v2.0)</td>
<td>PRO Personal</td> <td>PRO Personal</td>
<td>PRO Business</td> <td>PRO Business</td>
<td>PRO Enterprise</td> <td>PRO Enterprise</td>
@ -147,6 +148,14 @@ see what's new & breaking.
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr>
<td>npm module</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr> <tr>
<td>TypeScript declarations</td> <td>TypeScript declarations</td>
<td><a href="#demo" title="Community version">⚠️</a></td> <td><a href="#demo" title="Community version">⚠️</a></td>
@ -156,23 +165,7 @@ see what's new & breaking.
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>npm module available</td> <td>Allows commercial use</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Direct downloads available</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Allows commercial usage</td>
<td></td> <td></td>
<td></td> <td></td>
<td></td> <td></td>
@ -188,27 +181,11 @@ see what's new & breaking.
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>No open-source obligations</td> <td>Unlimited use per 1 license</td>
<td></td>
<td><strong title="Copyleft license"></strong></td>
<td></td> <td></td>
<td></td> <td></td>
<td></td> <td></td>
</tr> <td><strong title="1 project per 1 license"></strong></td>
<tr>
<td>Unlimited end-products</td>
<td></td>
<td></td>
<td></td>
<td><strong title="1 end-product per license"></strong></td>
<td></td>
</tr>
<tr>
<td>Unlimited deployments</td>
<td></td>
<td></td>
<td></td>
<td><strong title="1 TLD or deliverable per license"></strong></td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
@ -229,8 +206,8 @@ see what's new & breaking.
</tr> </tr>
<tr> <tr>
<td>Price</td> <td>Price</td>
<td><strong title="Pay as you want">FREE<sup>*</sup> (<a target="_blank" href="https://raw.githubusercontent.com/faisalman/ua-parser-js/1.0.x/license.md">License</a>)</strong></td> <td><strong title="Pay as you want">FREE (<a target="_blank" href="https://raw.githubusercontent.com/faisalman/ua-parser-js/1.0.x/license.md">License</a>)</strong></td>
<td><strong title="Pay as you want">FREE<sup>*</sup> (<a target="_blank" href="https://raw.githubusercontent.com/faisalman/ua-parser-js/master/LICENSE.md">License</a>)</strong></td> <td><strong title="Pay as you want">FREE (<a target="_blank" href="https://raw.githubusercontent.com/faisalman/ua-parser-js/master/LICENSE.md">License</a>)</strong></td>
<td><strong title="$14 (one-time fee)">$14 (<a target="_blank" href="https://raw.githubusercontent.com/faisalman/ua-parser-js/pro-personal/LICENSE.md">License</a>)</strong></td> <td><strong title="$14 (one-time fee)">$14 (<a target="_blank" href="https://raw.githubusercontent.com/faisalman/ua-parser-js/pro-personal/LICENSE.md">License</a>)</strong></td>
<td><strong title="$29 (one-time fee)">$29 (<a target="_blank" href="https://raw.githubusercontent.com/faisalman/ua-parser-js/pro-business/LICENSE.md">License</a>)</strong></td> <td><strong title="$29 (one-time fee)">$29 (<a target="_blank" href="https://raw.githubusercontent.com/faisalman/ua-parser-js/pro-business/LICENSE.md">License</a>)</strong></td>
<td><strong title="$599 (one-time fee)">$599 (<a target="_blank" href="https://raw.githubusercontent.com/faisalman/ua-parser-js/pro-enterprise/LICENSE.md">License</a>)</strong></td> <td><strong title="$599 (one-time fee)">$599 (<a target="_blank" href="https://raw.githubusercontent.com/faisalman/ua-parser-js/pro-enterprise/LICENSE.md">License</a>)</strong></td>
@ -259,7 +236,10 @@ Made with [contributors-img](https://contrib.rocks).
## Backers & Sponsors ## Backers & Sponsors
Support the **open-source editions** of UAParser.js through one of the following options: <a href="https://opencollective.com/ua-parser-js"><img src="https://opencollective.com/ua-parser-js/organizations.svg?avatarHeight=64"></a>
<a href="https://opencollective.com/ua-parser-js"><img src="https://opencollective.com/ua-parser-js/individuals.svg?avatarHeight=64"></a>
You can support the open-source editions of UAParser.js through one of the following options:
[![OpenCollective](https://img.shields.io/badge/OpenCollective-dddddd?style=for-the-badge&logo=opencollective&color=dddddd [![OpenCollective](https://img.shields.io/badge/OpenCollective-dddddd?style=for-the-badge&logo=opencollective&color=dddddd
)](https://opencollective.com/ua-parser-js) )](https://opencollective.com/ua-parser-js)
@ -268,7 +248,4 @@ Support the **open-source editions** of UAParser.js through one of the following
[![PayPal](https://img.shields.io/badge/Paypal-003087?style=for-the-badge&logo=paypal&color=003087 [![PayPal](https://img.shields.io/badge/Paypal-003087?style=for-the-badge&logo=paypal&color=003087
)](https://paypal.me/faisalman) )](https://paypal.me/faisalman)
[![WeChat/Alipay](https://img.shields.io/badge/Other_Payment_Methods-Alipay_/_WeChat_Pay-09b83e?style=for-the-badge&logo=mastercard&color=09b83e [![WeChat/Alipay](https://img.shields.io/badge/Other_Payment_Methods-Alipay_/_WeChat_Pay-09b83e?style=for-the-badge&logo=mastercard&color=09b83e
)](https://store.faisalman.com/buy/3d71f2f3-cf4d-473c-892a-9d4497c890be) )](https://store.faisalman.com/buy/3d71f2f3-cf4d-473c-892a-9d4497c890be)
<a href="https://opencollective.com/ua-parser-js"><img src="https://opencollective.com/ua-parser-js/organizations.svg?avatarHeight=64"></a>
<a href="https://opencollective.com/ua-parser-js"><img src="https://opencollective.com/ua-parser-js/individuals.svg?avatarHeight=64"></a>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

46
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "ua-parser-js", "name": "ua-parser-js",
"version": "2.0.5", "version": "2.0.4",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "ua-parser-js", "name": "ua-parser-js",
"version": "2.0.5", "version": "2.0.4",
"funding": [ "funding": [
{ {
"type": "opencollective", "type": "opencollective",
@ -1889,6 +1889,26 @@
"node": "^10 || ^12 || >=13.7" "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==",
"dev": true,
"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": { "node_modules/normalize-package-data": {
"version": "3.0.3", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz",
@ -2620,6 +2640,12 @@
"node": ">=8.0" "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==",
"dev": true
},
"node_modules/trim-newlines": { "node_modules/trim-newlines": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz",
@ -2712,6 +2738,22 @@
"spdx-expression-parse": "^3.0.0" "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==",
"dev": true
},
"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==",
"dev": true,
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"node_modules/which": { "node_modules/which": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",

View File

@ -1,7 +1,7 @@
{ {
"title": "UAParser.js", "title": "UAParser.js",
"name": "ua-parser-js", "name": "ua-parser-js",
"version": "2.0.5", "version": "2.0.4",
"author": "Faisal Salman <f@faisalman.com> (http://faisalman.com)", "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", "description": "Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent & Client Hints data. Supports browser & node.js environment",
"keywords": [ "keywords": [

View File

@ -3,7 +3,7 @@
// Source: /src/enums/ua-parser-enums.js // Source: /src/enums/ua-parser-enums.js
/////////////////////////////////////////////// ///////////////////////////////////////////////
/* Enums for UAParser.js v2.0.5 /* Enums for UAParser.js v2.0.4
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */
@ -285,7 +285,7 @@ export const DeviceVendor: Readonly<{
SPRINT: 'Sprint', SPRINT: 'Sprint',
TCL: 'TCL', TCL: 'TCL',
TECHNISAT: 'TechniSAT', TECHNISAT: 'TechniSAT',
TECNO: 'TECNO', TECNO: 'Tecno',
TESLA: 'Tesla', TESLA: 'Tesla',
ULEFONE: 'Ulefone', ULEFONE: 'Ulefone',
VIVO: 'Vivo', VIVO: 'Vivo',
@ -437,14 +437,15 @@ export const OS: typeof OSName;
export const Extension: Readonly<{ export const Extension: Readonly<{
BrowserName: { BrowserName: {
CLI: { CLIs: {
CURL: 'curl', CURL: 'curl',
ELINKS: 'ELinks', ELINKS: 'ELinks',
HTTPIE: 'HTTPie', HTTPIE: 'HTTPie',
LYNX: 'Lynx', LYNX: 'Lynx',
WGET: 'Wget' WGET: 'wget'
}, },
Crawler: { Crawlers: {
'360_SPIDER': '360Spider',
AHREFS_BOT: 'AhrefsBot', AHREFS_BOT: 'AhrefsBot',
AI2_BOT: 'AI2Bot', AI2_BOT: 'AI2Bot',
AIHIT_BOT: 'aiHitBot', AIHIT_BOT: 'aiHitBot',
@ -471,9 +472,9 @@ export const Extension: Readonly<{
BLEX_BOT: 'BLEXBot', BLEX_BOT: 'BLEXBot',
BOTIFY: 'botify', BOTIFY: 'botify',
BRAVE_BOT: 'Bravebot', BRAVE_BOT: 'Bravebot',
BYTEDANCE_BYTESPIDER: 'Bytespider', BYTEDANCE_SPIDER: 'Bytespider',
BYTEDANCE_TIKTOKSPIDER: 'TikTokSpider', CC_BOT: 'CCBot',
COMMON_CRAWL_CCBOT: 'CCBot', CHATGLM_SPIDER: 'ChatGLM-Spider',
COCCOC_BOT_WEB: 'coccocbot-web', COCCOC_BOT_WEB: 'coccocbot-web',
COCCOC_BOT_IMAGE: 'coccocbot-image', COCCOC_BOT_IMAGE: 'coccocbot-image',
COHERE_TRAINING_DATA_CRAWLER: 'cohere-training-data-crawler', COHERE_TRAINING_DATA_CRAWLER: 'cohere-training-data-crawler',
@ -495,13 +496,10 @@ export const Extension: Readonly<{
GOOGLE_ADSBOT: 'AdsBot-Google', GOOGLE_ADSBOT: 'AdsBot-Google',
GOOGLE_ADSBOT_MOBILE: 'Adsbot-Google-Mobile', GOOGLE_ADSBOT_MOBILE: 'Adsbot-Google-Mobile',
GOOGLE_ADSENSE: 'AdSense', GOOGLE_ADSENSE: 'AdSense',
GOOGLE_APIS: 'APIs-Google',
GOOGLE_BOT: 'Googlebot', GOOGLE_BOT: 'Googlebot',
GOOGLE_BOT_IMAGE: 'Googlebot-Image', GOOGLE_BOT_IMAGE: 'Googlebot-Image',
GOOGLE_BOT_NEWS: 'Googlebot-News', GOOGLE_BOT_NEWS: 'Googlebot-News',
GOOGLE_BOT_VIDEO: 'Googlebot-Video', GOOGLE_BOT_VIDEO: 'Googlebot-Video',
GOOGLE_CLOUDVERTEXBOT: 'Google-CloudVertexBot',
GOOGLE_EXTENDED: 'Google-Extended',
GOOGLE_INSPECTIONTOOL: 'Google-InspectionTool', GOOGLE_INSPECTIONTOOL: 'Google-InspectionTool',
GOOGLE_OTHER: 'GoogleOther', GOOGLE_OTHER: 'GoogleOther',
GOOGLE_OTHER_IMAGE: 'GoogleOther-Image', GOOGLE_OTHER_IMAGE: 'GoogleOther-Image',
@ -531,16 +529,16 @@ export const Extension: Readonly<{
MICROSOFT_ADIDXBOT: 'adidxbot', MICROSOFT_ADIDXBOT: 'adidxbot',
MOJEEK_BOT: 'MojeekBot', MOJEEK_BOT: 'MojeekBot',
MOZ_DOTBOT: 'DotBot', MOZ_DOTBOT: 'DotBot',
OMGILI: 'omgili',
OMGILI_BOT: 'omgilibot',
ONCRAWL: 'OnCrawl', ONCRAWL: 'OnCrawl',
ONESPOT_SCRAPERBOT: 'Onespot-ScraperBot', ONESPOT_SCRAPERBOT: 'Onespot-ScraperBot',
OPENAI_GPTBOT: 'GPTBot', OPENAI_GPTBOT: 'GPTBot',
OPENAI_SEARCH_BOT: 'OAI-SearchBot', OPENAI_SEARCH: 'OAI-SearchBot',
PERPLEXITY_BOT: 'PerplexityBot', PERPLEXITY_BOT: 'PerplexityBot',
QIHOO_360_SPIDER: '360Spider',
QWANT_BOT: 'Qwantbot', QWANT_BOT: 'Qwantbot',
REPLICATE_BOT: 'Replicate-Bot', REPLICATE_BOT: 'Replicate-Bot',
RUNPOD_BOT: 'RunPod-Bot', RUNPOD_BOT: 'RunPod-Bot',
SB_INTUITIONS_BOT: 'SBIntuitionsBot',
SEEKPORT_BOT: 'SeekportBot', SEEKPORT_BOT: 'SeekportBot',
SEMRUSH_BOT: 'SemrushBot', SEMRUSH_BOT: 'SemrushBot',
SEMRUSH_BOT_BACKLINK: 'SemrushBot-BA', SEMRUSH_BOT_BACKLINK: 'SemrushBot-BA',
@ -555,51 +553,18 @@ export const Extension: Readonly<{
TOGETHER_BOT: 'Together-Bot', TOGETHER_BOT: 'Together-Bot',
TURNITIN_BOT: 'TurnitinBot', TURNITIN_BOT: 'TurnitinBot',
TWIN_AGENT: 'TwinAgent', TWIN_AGENT: 'TwinAgent',
VERCEL_V0BOT: 'v0bot',
WEBZIO: 'webzio',
WEBZIO_EXTENDED: 'Webzio-Extended',
WEBZIO_OMGILI: 'omgili',
WEBZIO_OMGILI_BOT: 'omgilibot',
XAI_BOT: 'xAI-Bot', XAI_BOT: 'xAI-Bot',
VERCEL_V0BOT: 'v0bot',
YAHOO_JAPAN: 'Y!J-BRW', YAHOO_JAPAN: 'Y!J-BRW',
YAHOO_SLURP: 'Yahoo! Slurp', YAHOO_SLURP: 'Yahoo! Slurp',
YANDEX_ACCESSIBILITY_BOT: 'YandexAccessibilityBot',
YANDEX_ADDITIONAL_BOT: 'YandexAdditionalBot',
YANDEX_ADNET: 'YandexAdNet',
YANDEX_BLOGS: 'YandexBlogs',
YANDEX_BOT: 'YandexBot', 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', YEP_BOT: 'YepBot',
YETI: 'Yeti', YETI: 'Yeti',
YISOU_SPIDER: 'YisouSpider', YISOU_SPIDER: 'YisouSpider',
YOU_BOT: 'YouBot', YOU_BOT: 'YouBot',
ZHIPU_CHATGLM_SPIDER: 'ChatGLM-Spider',
ZUM_BOT: 'ZumBot' ZUM_BOT: 'ZumBot'
}, },
Email: { Emails: {
AIRMAIL: 'Airmail', AIRMAIL: 'Airmail',
APPLE_MAIL: 'Mail', APPLE_MAIL: 'Mail',
BLUEMAIL: 'BlueMail', BLUEMAIL: 'BlueMail',
@ -622,7 +587,7 @@ export const Extension: Readonly<{
ZIMBRA: 'Zimbra', ZIMBRA: 'Zimbra',
ZOHO_MAIL: 'ZohoMail-Desktop' ZOHO_MAIL: 'ZohoMail-Desktop'
}, },
Fetcher: { Fetchers: {
AHREFS_SITEAUDIT: 'AhrefsSiteAudit', AHREFS_SITEAUDIT: 'AhrefsSiteAudit',
ANTHROPIC_CLAUDE_USER: 'Claude-User', ANTHROPIC_CLAUDE_USER: 'Claude-User',
ASANA: 'Asana', ASANA: 'Asana',
@ -635,7 +600,7 @@ export const Extension: Readonly<{
GOOGLE_CHROME_LIGHTHOUSE: 'Chrome-Lighthouse', GOOGLE_CHROME_LIGHTHOUSE: 'Chrome-Lighthouse',
GOOGLE_FEEDFETCHER: 'FeedFetcher-Google', GOOGLE_FEEDFETCHER: 'FeedFetcher-Google',
GOOGLE_GEMINI_DEEP_RESEARCH: 'Gemini-Deep-Research', GOOGLE_GEMINI_DEEP_RESEARCH: 'Gemini-Deep-Research',
GOOGLE_IMAGEPROXY: 'GoogleImageProxy', GOOGLE_IMAGE_PROXY: 'GoogleImageProxy',
GOOGLE_PAGERENDERER: 'Google-PageRenderer', GOOGLE_PAGERENDERER: 'Google-PageRenderer',
GOOGLE_READ_ALOUD: 'Google-Read-Aloud', GOOGLE_READ_ALOUD: 'Google-Read-Aloud',
GOOGLE_PRODUCER: 'GoogleProducer', GOOGLE_PRODUCER: 'GoogleProducer',
@ -644,7 +609,6 @@ export const Extension: Readonly<{
IFRAMELY: 'Iframely', IFRAMELY: 'Iframely',
KAKAOTALK_SCRAP: 'kakaotalk-scrap', KAKAOTALK_SCRAP: 'kakaotalk-scrap',
META_EXTERNALFETCHER: 'meta-externalfetcher', META_EXTERNALFETCHER: 'meta-externalfetcher',
META_WHATSAPP: 'WhatsApp',
MICROSOFT_BINGPREVIEW: 'BingPreview', MICROSOFT_BINGPREVIEW: 'BingPreview',
MICROSOFT_PREVIEW: 'MicrosoftPreview', MICROSOFT_PREVIEW: 'MicrosoftPreview',
MISTRALAI_USER: 'MistralAI-User', MISTRALAI_USER: 'MistralAI-User',
@ -657,24 +621,17 @@ export const Extension: Readonly<{
SNAP_URL_PREVIEW: 'Snap URL Preview', SNAP_URL_PREVIEW: 'Snap URL Preview',
SKYPE_URIPREVIEW: 'SkypeUriPreview', SKYPE_URIPREVIEW: 'SkypeUriPreview',
TELEGRAM_BOT: 'TelegramBot', TELEGRAM_BOT: 'TelegramBot',
TIKTOK_SPIDER: 'TikTokSpider',
UPTIMEROBOT: 'UptimeRobot', UPTIMEROBOT: 'UptimeRobot',
VERCEL_FAVICON_BOT: 'vercel-favicon-bot', VERCEL_FAVICON_BOT: 'vercel-favicon-bot',
VERCEL_SCREENSHOT_BOT: 'vercel-screenshot-bot', VERCEL_SCREENSHOT_BOT: 'vercel-screenshot-bot',
VERCEL_BOT: 'Vercelbot', VERCEL_BOT: 'Vercelbot',
VERCEL_FLAGS: 'vercelflags', VERCEL_FLAGS: 'vercelflags',
VERCEL_TRACING: 'verceltracing', VERCEL_TRACING: 'verceltracing',
YANDEX_CALENDAR: 'YandexCalendar', WHATSAPP: 'WhatsApp',
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' ZOOMINFO_BOT: 'Zoombot'
}, },
InApp: { InApps: {
DISCORD: 'Discord', DISCORD: 'Discord',
EVERNOTE: 'Evernote', EVERNOTE: 'Evernote',
FIGMA: 'Figma', FIGMA: 'Figma',
@ -690,7 +647,7 @@ export const Extension: Readonly<{
VSCODE: 'VS Code', VSCODE: 'VS Code',
YAHOO_JAPAN: 'Yahoo! Japan' YAHOO_JAPAN: 'Yahoo! Japan'
}, },
Library: { Libraries: {
ADOBE_AIR: 'AdobeAIR', ADOBE_AIR: 'AdobeAIR',
AIOHTTP: 'aiohttp', AIOHTTP: 'aiohttp',
APACHE_HTTPCLIENT: 'Apache-HttpClient', APACHE_HTTPCLIENT: 'Apache-HttpClient',
@ -718,7 +675,7 @@ export const Extension: Readonly<{
} }
}, },
DeviceVendor: { DeviceVendor: {
Vehicle: { Vehicles: {
BMW: 'BMW', BMW: 'BMW',
BYD: 'BYD', BYD: 'BYD',
JEEP: 'Jeep', JEEP: 'Jeep',

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////// ///////////////////////////////////////////////
/* Enums for UAParser.js v2.0.5 /* Enums for UAParser.js v2.0.4
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */
@ -281,7 +281,7 @@ const DeviceVendor = Object.freeze({
SPRINT: 'Sprint', SPRINT: 'Sprint',
TCL: 'TCL', TCL: 'TCL',
TECHNISAT: 'TechniSAT', TECHNISAT: 'TechniSAT',
TECNO: 'TECNO', TECNO: 'Tecno',
TESLA: 'Tesla', TESLA: 'Tesla',
ULEFONE: 'Ulefone', ULEFONE: 'Ulefone',
VIVO: 'Vivo', VIVO: 'Vivo',
@ -433,14 +433,14 @@ const OS = OSName;
const Extension = Object.freeze({ const Extension = Object.freeze({
BrowserName: { BrowserName: {
CLI: { CLIs: {
CURL: 'curl', CURL: 'curl',
ELINKS: 'ELinks', ELINKS: 'ELinks',
HTTPIE: 'HTTPie', HTTPIE: 'HTTPie',
LYNX: 'Lynx', LYNX: 'Lynx',
WGET: 'Wget' WGET: 'wget'
}, },
Crawler: { Crawlers: {
AHREFS_BOT: 'AhrefsBot', AHREFS_BOT: 'AhrefsBot',
AI2_BOT: 'AI2Bot', AI2_BOT: 'AI2Bot',
AIHIT_BOT: 'aiHitBot', AIHIT_BOT: 'aiHitBot',
@ -595,7 +595,7 @@ const Extension = Object.freeze({
ZHIPU_CHATGLM_SPIDER: 'ChatGLM-Spider', ZHIPU_CHATGLM_SPIDER: 'ChatGLM-Spider',
ZUM_BOT: 'ZumBot' ZUM_BOT: 'ZumBot'
}, },
Email: { Emails: {
AIRMAIL: 'Airmail', AIRMAIL: 'Airmail',
APPLE_MAIL: 'Mail', APPLE_MAIL: 'Mail',
BLUEMAIL: 'BlueMail', BLUEMAIL: 'BlueMail',
@ -618,7 +618,7 @@ const Extension = Object.freeze({
ZIMBRA: 'Zimbra', ZIMBRA: 'Zimbra',
ZOHO_MAIL: 'ZohoMail-Desktop' ZOHO_MAIL: 'ZohoMail-Desktop'
}, },
Fetcher: { Fetchers: {
AHREFS_SITEAUDIT: 'AhrefsSiteAudit', AHREFS_SITEAUDIT: 'AhrefsSiteAudit',
ANTHROPIC_CLAUDE_USER: 'Claude-User', ANTHROPIC_CLAUDE_USER: 'Claude-User',
ASANA: 'Asana', ASANA: 'Asana',
@ -640,7 +640,6 @@ const Extension = Object.freeze({
IFRAMELY: 'Iframely', IFRAMELY: 'Iframely',
KAKAOTALK_SCRAP: 'kakaotalk-scrap', KAKAOTALK_SCRAP: 'kakaotalk-scrap',
META_EXTERNALFETCHER: 'meta-externalfetcher', META_EXTERNALFETCHER: 'meta-externalfetcher',
META_WHATSAPP: 'WhatsApp',
MICROSOFT_BINGPREVIEW: 'BingPreview', MICROSOFT_BINGPREVIEW: 'BingPreview',
MICROSOFT_PREVIEW: 'MicrosoftPreview', MICROSOFT_PREVIEW: 'MicrosoftPreview',
MISTRALAI_USER: 'MistralAI-User', MISTRALAI_USER: 'MistralAI-User',
@ -653,6 +652,7 @@ const Extension = Object.freeze({
SNAP_URL_PREVIEW: 'Snap URL Preview', SNAP_URL_PREVIEW: 'Snap URL Preview',
SKYPE_URIPREVIEW: 'SkypeUriPreview', SKYPE_URIPREVIEW: 'SkypeUriPreview',
TELEGRAM_BOT: 'TelegramBot', TELEGRAM_BOT: 'TelegramBot',
TIKTOK_SPIDER: 'TikTokSpider',
UPTIMEROBOT: 'UptimeRobot', UPTIMEROBOT: 'UptimeRobot',
VERCEL_FAVICON_BOT: 'vercel-favicon-bot', VERCEL_FAVICON_BOT: 'vercel-favicon-bot',
VERCEL_SCREENSHOT_BOT: 'vercel-screenshot-bot', VERCEL_SCREENSHOT_BOT: 'vercel-screenshot-bot',
@ -668,9 +668,10 @@ const Extension = Object.freeze({
YANDEX_SEARCHSHOP: 'YandexSearchShop', YANDEX_SEARCHSHOP: 'YandexSearchShop',
YANDEX_SITELINKS: 'YandexSitelinks', YANDEX_SITELINKS: 'YandexSitelinks',
YANDEX_USERPROXY: 'YandexUserproxy', YANDEX_USERPROXY: 'YandexUserproxy',
WHATSAPP: 'WhatsApp',
ZOOMINFO_BOT: 'Zoombot' ZOOMINFO_BOT: 'Zoombot'
}, },
InApp: { InApps: {
DISCORD: 'Discord', DISCORD: 'Discord',
EVERNOTE: 'Evernote', EVERNOTE: 'Evernote',
FIGMA: 'Figma', FIGMA: 'Figma',
@ -686,7 +687,7 @@ const Extension = Object.freeze({
VSCODE: 'VS Code', VSCODE: 'VS Code',
YAHOO_JAPAN: 'Yahoo! Japan' YAHOO_JAPAN: 'Yahoo! Japan'
}, },
Library: { Libraries: {
ADOBE_AIR: 'AdobeAIR', ADOBE_AIR: 'AdobeAIR',
AIOHTTP: 'aiohttp', AIOHTTP: 'aiohttp',
APACHE_HTTPCLIENT: 'Apache-HttpClient', APACHE_HTTPCLIENT: 'Apache-HttpClient',
@ -714,7 +715,7 @@ const Extension = Object.freeze({
} }
}, },
DeviceVendor: { DeviceVendor: {
Vehicle: { Vehicles: {
BMW: 'BMW', BMW: 'BMW',
BYD: 'BYD', BYD: 'BYD',
JEEP: 'Jeep', JEEP: 'Jeep',

View File

@ -3,7 +3,7 @@
// Source: /src/enums/ua-parser-enums.js // Source: /src/enums/ua-parser-enums.js
/////////////////////////////////////////////// ///////////////////////////////////////////////
/* Enums for UAParser.js v2.0.5 /* Enums for UAParser.js v2.0.4
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */
@ -11,7 +11,7 @@
/*jshint esversion: 6 */ /*jshint esversion: 6 */
const BrowserName = Object.freeze({ const Browser = Object.freeze({
'115': '115', '115': '115',
'2345': '2345', '2345': '2345',
'360': '360', '360': '360',
@ -162,15 +162,10 @@ const BrowserName = Object.freeze({
WEIBO: 'Weibo', WEIBO: 'Weibo',
WHALE: 'Whale', WHALE: 'Whale',
WOLVIC: 'Wolvic', WOLVIC: 'Wolvic',
YANDEX: 'Yandex', YANDEX: 'Yandex'
ZALO: 'Zalo'
// TODO : test! // TODO : test!
}); });
/**
* @deprecated Use `BrowserName` instead
*/
const Browser = BrowserName;
const BrowserType = Object.freeze({ const BrowserType = Object.freeze({
CRAWLER: 'crawler', CRAWLER: 'crawler',
@ -182,9 +177,8 @@ const BrowserType = Object.freeze({
LIBRARY: 'library' LIBRARY: 'library'
}); });
const CPUArch = Object.freeze({ const CPU = Object.freeze({
'68K': '68k', '68K': '68k',
ALPHA: 'alpha',
ARM : 'arm', ARM : 'arm',
ARM_64: 'arm64', ARM_64: 'arm64',
ARM_HF: 'armhf', ARM_HF: 'armhf',
@ -202,12 +196,8 @@ const CPUArch = Object.freeze({
X86: 'ia32', X86: 'ia32',
X86_64: 'amd64' X86_64: 'amd64'
}); });
/**
* @deprecated Use `CPUArch` instead
*/
const CPU = CPUArch;
const DeviceType = Object.freeze({ const Device = Object.freeze({
CONSOLE: 'console', CONSOLE: 'console',
DESKTOP: 'desktop', DESKTOP: 'desktop',
EMBEDDED: 'embedded', EMBEDDED: 'embedded',
@ -217,12 +207,8 @@ const DeviceType = Object.freeze({
WEARABLE: 'wearable', WEARABLE: 'wearable',
XR: 'xr' XR: 'xr'
}); });
/**
* @deprecated Use `DeviceType` instead
*/
const Device = DeviceType;
const DeviceVendor = Object.freeze({ const Vendor = Object.freeze({
ACER: 'Acer', ACER: 'Acer',
ADVAN: 'Advan', ADVAN: 'Advan',
ALCATEL: 'Alcatel', ALCATEL: 'Alcatel',
@ -270,7 +256,6 @@ const DeviceVendor = Object.freeze({
PALM: 'Palm', PALM: 'Palm',
PANASONIC: 'Panasonic', PANASONIC: 'Panasonic',
PEBBLE: 'Pebble', PEBBLE: 'Pebble',
PHILIPS: 'Philips',
PICO: 'Pico', PICO: 'Pico',
POLYTRON: 'Polytron', POLYTRON: 'Polytron',
REALME: 'Realme', REALME: 'Realme',
@ -285,7 +270,7 @@ const DeviceVendor = Object.freeze({
SPRINT: 'Sprint', SPRINT: 'Sprint',
TCL: 'TCL', TCL: 'TCL',
TECHNISAT: 'TechniSAT', TECHNISAT: 'TechniSAT',
TECNO: 'TECNO', TECNO: 'Tecno',
TESLA: 'Tesla', TESLA: 'Tesla',
ULEFONE: 'Ulefone', ULEFONE: 'Ulefone',
VIVO: 'Vivo', VIVO: 'Vivo',
@ -298,12 +283,8 @@ const DeviceVendor = Object.freeze({
// TODO : test! // TODO : test!
}); });
/**
* @deprecated Use `DeviceVendor` instead
*/
const Vendor = DeviceVendor;
const EngineName = Object.freeze({ const Engine = Object.freeze({
AMAYA: 'Amaya', AMAYA: 'Amaya',
ARKWEB: 'ArkWeb', ARKWEB: 'ArkWeb',
BLINK: 'Blink', BLINK: 'Blink',
@ -325,12 +306,8 @@ const EngineName = Object.freeze({
W3M: 'w3m', W3M: 'w3m',
WEBKIT: 'WebKit' WEBKIT: 'WebKit'
}); });
/**
* @deprecated Use `EngineName` instead
*/
const Engine = EngineName;
const OSName = Object.freeze({ const OS = Object.freeze({
AIX: 'AIX', AIX: 'AIX',
AMIGA_OS: 'Amiga OS', AMIGA_OS: 'Amiga OS',
ANDROID: 'Android', ANDROID: 'Android',
@ -426,322 +403,13 @@ const OSName = Object.freeze({
// TODO : test! // 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',
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',
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',
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',
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',
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',
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',
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 { export {
Browser,// deprecated Browser,
CPU, // deprecated
Device, // deprecated
Vendor, // deprecated
Engine, // deprecated
OS, // deprecated
BrowserName,
BrowserType, BrowserType,
CPUArch, CPU,
DeviceType, Device,
DeviceVendor, Vendor,
EngineName, Engine,
OSName, OS
Extension
}; };

View File

@ -1,4 +1,4 @@
// Type definitions for Helpers submodule of UAParser.js v2.0.5 // Type definitions for Helpers submodule of UAParser.js v2.0.4
// Project: https://github.com/faisalman/ua-parser-js // Project: https://github.com/faisalman/ua-parser-js
// Definitions by: Faisal Salman <https://github.com/faisalman> // Definitions by: Faisal Salman <https://github.com/faisalman>

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////// ///////////////////////////////////////////////
/* Extensions for UAParser.js v2.0.5 /* Extensions for UAParser.js v2.0.4
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */
@ -283,8 +283,8 @@ const Fetchers = Object.freeze({
[NAME, VERSION, [TYPE, FETCHER]], [NAME, VERSION, [TYPE, FETCHER]],
[ [
// Google Bots / Chrome-Lighthouse / Gemini-Deep-Research / Snapchat / Vercelbot / Yandex Bots // Google Bots / Chrome-Lighthouse / Gemini-Deep-Research / Snapchat / TikTokSpider / Vercelbot / Yandex Bots
/((?:better uptime |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 /((?:better uptime |telegram|vercel)bot|chrome-lighthouse|feedfetcher-google|gemini-deep-research|google(?:imageproxy|-read-aloud|-pagerenderer|producer)|snap url preview|tiktokspider|vercel(flags|tracing|-(favicon|screenshot)-bot)|yandex(?:sitelinks|userproxy))/i
], ],
[NAME, [TYPE, FETCHER]], [NAME, [TYPE, FETCHER]],
], ],

View File

@ -3,7 +3,7 @@
// Source: /src/extensions/ua-parser-extensions.js // Source: /src/extensions/ua-parser-extensions.js
/////////////////////////////////////////////// ///////////////////////////////////////////////
/* Extensions for UAParser.js v2.0.5 /* Extensions for UAParser.js v2.0.4
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */
@ -47,31 +47,20 @@ const Crawlers = Object.freeze({
// AhrefsBot - https://ahrefs.com/robot // AhrefsBot - https://ahrefs.com/robot
// Amazonbot - https://developer.amazon.com/amazonbot // Amazonbot - https://developer.amazon.com/amazonbot
// Bingbot / AdIdxBot - https://www.bing.com/webmasters/help/which-crawlers-does-bing-use-8c184ec0 // 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 // 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 // Dotbot - https://moz.com/help/moz-procedures/crawlers/dotbot
// DuckDuckBot - http://duckduckgo.com/duckduckbot.html // DuckDuckBot - http://duckduckgo.com/duckduckbot.html
// FacebookBot - https://developers.facebook.com/docs/sharing/bot/ // FacebookBot - https://developers.facebook.com/docs/sharing/bot/
// GPTBot - https://platform.openai.com/docs/gptbot // GPTBot - https://platform.openai.com/docs/gptbot
// iAskBot - https://iask.ai // iAskBot - https://iask.ai
// Kagibot - https://kagi.com/bot
// Kangaroo Bot - https://kangaroollm.com.au/kangaroo-bot/
// LinkedInBot - http://www.linkedin.com // LinkedInBot - http://www.linkedin.com
// MJ12bot - https://mj12bot.com/ // MJ12bot - https://mj12bot.com/
// MojeekBot - https://www.mojeek.com/bot.html // MojeekBot - https://www.mojeek.com/bot.html
// Onespot - https://www.onespot.com/identifying-traffic.html // Onespot - https://www.onespot.com/identifying-traffic.html
// OpenAI's SearchGPT - https://platform.openai.com/docs/bots // OpenAI's SearchGPT - https://platform.openai.com/docs/bots
// PerplexityBot - https://perplexity.ai/perplexitybot // PerplexityBot - https://perplexity.ai/perplexitybot
// SBIntuitionsBot - https://www.sbintuitions.co.jp/bot/
// SeznamBot - http://napoveda.seznam.cz/seznambot-intro // SeznamBot - http://napoveda.seznam.cz/seznambot-intro
// YepBot - https://yep.com/yepbot/ /((?:adidx|ahrefs|amazon|bing|cc|dot|duckduck|exa|facebook|gpt|iask|linkedin|mj12|mojeek|oai-search|onespot-scraper|perplexity|semrush|seznam)bot)\/([\w\.-]+)/i,
/((?: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|yep)bot)\/([\w\.-]+)/i,
// Algolia Crawler
/(algolia crawler(?: renderscript)?)\/?([\w\.]*)/i,
// Applebot - http://apple.com/go/applebot // Applebot - http://apple.com/go/applebot
/(applebot(?:-extended)?)\/?([\w\.]*)/i, /(applebot(?:-extended)?)\/?([\w\.]*)/i,
@ -80,7 +69,7 @@ const Crawlers = Object.freeze({
/(baiduspider[-imagevdonwsfcpr]{0,7})\/?([\w\.]*)/i, /(baiduspider[-imagevdonwsfcpr]{0,7})\/?([\w\.]*)/i,
// ClaudeBot (Anthropic) // ClaudeBot (Anthropic)
/(claude(?:bot|-searchbot|-web)|anthropic-ai)\/?([\w\.]*)/i, /(claude(?:bot|-web)|anthropic-ai)\/?([\w\.]*)/i,
// Coc Coc Bot - https://help.coccoc.com/en/search-engine // Coc Coc Bot - https://help.coccoc.com/en/search-engine
/(coccocbot-(?:image|web))\/([\w\.]+)/i, /(coccocbot-(?:image|web))\/([\w\.]+)/i,
@ -98,9 +87,6 @@ const Crawlers = Object.freeze({
// Internet Archive (archive.org) // Internet Archive (archive.org)
/(ia_archiver|archive\.org_bot)\/?([\w\.]*)/i, /(ia_archiver|archive\.org_bot)\/?([\w\.]*)/i,
// OnCrawl
/(oncrawl) mobile\/([\w\.]+)/i,
// Qwantbot - https://help.qwant.com/bot // Qwantbot - https://help.qwant.com/bot
/(qwantbot)[-\w]*\/?([\w\.]*)/i, /(qwantbot)[-\w]*\/?([\w\.]*)/i,
@ -114,38 +100,30 @@ const Crawlers = Object.freeze({
/(y!?j-(?:asr|br[uw]|dscv|mmp|vsidx|wsc))\/([\w\.]+)/i, /(y!?j-(?:asr|br[uw]|dscv|mmp|vsidx|wsc))\/([\w\.]+)/i,
// Yandex Bots - https://yandex.com/bots // Yandex Bots - https://yandex.com/bots
/(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, /(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,
// Yeti (Naver) // Yeti (Naver)
/(yeti)\/([\w\.]+)/i, /(yeti)\/([\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 // aiHitBot / Diffbot / Linespider / Magpie-Crawler / Omgilibot / OpenAI Image Downloader / Webzio-Extended / Screaming Frog SEO Spider / Startpage / Timpibot / VelenPublicWebCrawler / YisouSpider / YouBot
// Cotoyogi - https://ds.rois.ac.jp/en_center8/en_crawler/ /((?: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
// 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]],
[ [NAME, VERSION, [TYPE, CRAWLER]],
// YandexBot MirrorDetector
/(yandexbot\/([\w\.]+); mirrordetector)/i
],
[[NAME, /\/.+;/ig, ''], VERSION, [TYPE, CRAWLER]],
[ [
// Google Bots // Google Bots
/((?:adsbot|apis|mediapartners)-google(?:-mobile)?|google-?(?:other|cloudvertexbot|extended|safety))/i, /((?:adsbot|apis|mediapartners)-google(?:-mobile)?|google-?(?:other|cloudvertexbot|extended|safety))/i,
// AI2Bot - https://allenai.org/crawler // AI2Bot - https://allenai.org/crawler
// Bytespider
// DataForSeoBot - https://dataforseo.com/dataforseo-bot // DataForSeoBot - https://dataforseo.com/dataforseo-bot
// Huawei AspiegelBot / PetalBot https://aspiegel.com/petalbot // Huawei AspiegelBot / PetalBot https://aspiegel.com/petalbot
// ImagesiftBot - https://imagesift.com/about // ImagesiftBot - https://imagesift.com/about
// Siteimprove - https://help.siteimprove.com/support/solutions/articles/80000448553 // Qihoo 360Spider
// TurnitinBot - https://www.turnitin.com/robot/crawlerinfo.html // 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 // Yahoo! Slurp - http://help.yahoo.com/help/us/ysearch/slurp
// Botify / Bytespider / DeepSeekBot / Qihoo 360Spider / SeekportBot / TikTokSpider /\b(360spider-?(?:image|video)?|bytespider|(?:ai2|aspiegel|dataforseo|imagesift|petal|turnitin)bot|teoma|yahoo! slurp)/i
/\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]] [NAME, [TYPE, CRAWLER]]
] ]
@ -260,17 +238,16 @@ const Emails = Object.freeze({
const Fetchers = Object.freeze({ const Fetchers = Object.freeze({
browser : [ 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 // 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 // ChatGPT-User - https://platform.openai.com/docs/plugins/bot
// DuckAssistBot - https://duckduckgo.com/duckassistbot/ // DuckAssistBot - https://duckduckgo.com/duckassistbot/
// Better Uptime / BingPreview / Mastodon / MicrosoftPreview / Pinterestbot / Redditbot / Rogerbot / SiteAuditBot / Telegrambot / Twitterbot / UptimeRobot
// Google Site Verifier / Meta / Yahoo! Japan // Google Site Verifier / Meta / Yahoo! Japan
// Iframely - https://iframely.com/docs/about // Iframely - https://iframely.com/docs/about
// Perplexity-User - https://docs.perplexity.ai/guides/bots // Perplexity-User - https://docs.perplexity.ai/guides/bots
// MistralAI-User - https://docs.mistral.ai/robots/ // MistralAI-User - https://docs.mistral.ai/robots/
// Yandex Bots - https://yandex.com/bots // Yandex Bots - https://yandex.com/bots
/(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, /(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,
// Bluesky // Bluesky
/(bluesky) cardyb\/([\w\.]+)/i, /(bluesky) cardyb\/([\w\.]+)/i,
@ -287,8 +264,8 @@ const Fetchers = Object.freeze({
[NAME, VERSION, [TYPE, FETCHER]], [NAME, VERSION, [TYPE, FETCHER]],
[ [
// Google Bots / Chrome-Lighthouse / Gemini-Deep-Research / Snapchat / Vercelbot / Yandex Bots // Google Bots / Cohere / Snapchat / Vercelbot / Yandex Bots
/((?:better uptime |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 /((?:better uptime |telegram|vercel)bot|cohere-ai|feedfetcher-google|google(?:imageproxy|-read-aloud|-pagerenderer|producer)|snap url preview|yandex(?:sitelinks|userproxy))/i
], ],
[NAME, [TYPE, FETCHER]], [NAME, [TYPE, FETCHER]],
], ],
@ -431,8 +408,8 @@ const Vehicles = Object.freeze({
const Bots = Object.freeze({ const Bots = Object.freeze({
browser : [ browser : [
...CLIs.browser, ...CLIs.browser,
...Fetchers.browser,
...Crawlers.browser, ...Crawlers.browser,
...Fetchers.browser,
...Libraries.browser ...Libraries.browser
], ],
os : [ os : [

View File

@ -1,4 +1,4 @@
// Type definitions for Helpers submodule of UAParser.js v2.0.5 // Type definitions for Helpers submodule of UAParser.js v2.0.4
// Project: https://github.com/faisalman/ua-parser-js // Project: https://github.com/faisalman/ua-parser-js
// Definitions by: Faisal Salman <https://github.com/faisalman> // Definitions by: Faisal Salman <https://github.com/faisalman>

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////// ///////////////////////////////////////////////
/* Helpers for UAParser.js v2.0.5 /* Helpers for UAParser.js v2.0.4
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */
@ -8,12 +8,11 @@
/*jshint esversion: 6 */ /*jshint esversion: 6 */
const { UAParser } = require('../main/ua-parser'); const { UAParser } = require('../main/ua-parser');
const { CPUArch, OSName, EngineName, Extension, BrowserType } = require('../enums/ua-parser-enums'); const { CPUArch, OSName, EngineName, Extension } = require('../enums/ua-parser-enums');
const { Bots, Crawlers } = require('../extensions/ua-parser-extensions'); const { Bots } = require('../extensions/ua-parser-extensions');
const { isFromEU } = require('detect-europe-js'); const { isFromEU } = require('detect-europe-js');
const { isFrozenUA } = require('ua-is-frozen'); const { isFrozenUA } = require('ua-is-frozen');
const { isStandalonePWA } = require('is-standalone-pwa'); const { isStandalonePWA } = require('is-standalone-pwa');
const { Crawler } = Extension.BrowserName;
const toResult = (value, head, ext) => typeof value === 'string' ? UAParser(value, head, ext) : value; const toResult = (value, head, ext) => typeof value === 'string' ? UAParser(value, head, ext) : value;
@ -42,6 +41,7 @@ const isAppleSilicon = (resultOrUA) => {
return false; return false;
} }
const Crawler = Extension.BrowserName.Crawlers;
const isAIBot = (resultOrUA) => [ const isAIBot = (resultOrUA) => [
// AI2 // AI2
@ -158,13 +158,13 @@ const isAIBot = (resultOrUA) => [
Crawler.ZHIPU_CHATGLM_SPIDER Crawler.ZHIPU_CHATGLM_SPIDER
] ]
.map((s) => s.toLowerCase()) .map((s) => s.toLowerCase())
.includes(String(toResult(resultOrUA, Crawlers).browser.name).toLowerCase()); .includes(String(toResult(resultOrUA, Bots).browser.name).toLowerCase());
const isBot = (resultOrUA) => [ const isBot = (resultOrUA) => [
BrowserType.CLI, 'cli',
BrowserType.CRAWLER, 'crawler',
BrowserType.FETCHER, 'fetcher',
BrowserType.LIBRARY 'library'
].includes(toResult(resultOrUA, Bots).browser.type); ].includes(toResult(resultOrUA, Bots).browser.type);
const isChromeFamily = (resultOrUA) => toResult(resultOrUA).engine.is(EngineName.BLINK); const isChromeFamily = (resultOrUA) => toResult(resultOrUA).engine.is(EngineName.BLINK);

View File

@ -3,7 +3,7 @@
// Source: /src/helpers/ua-parser-helpers.js // Source: /src/helpers/ua-parser-helpers.js
/////////////////////////////////////////////// ///////////////////////////////////////////////
/* Helpers for UAParser.js v2.0.5 /* Helpers for UAParser.js v2.0.4
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */
@ -12,12 +12,11 @@
/*jshint esversion: 6 */ /*jshint esversion: 6 */
import { UAParser } from '../main/ua-parser.mjs'; import { UAParser } from '../main/ua-parser.mjs';
import { CPUArch, OSName, EngineName, Extension, BrowserType } from '../enums/ua-parser-enums.mjs'; import { CPU, OS, Engine } from '../enums/ua-parser-enums.mjs';
import { Bots, Crawlers } from '../extensions/ua-parser-extensions.mjs'; import { Bots } from '../extensions/ua-parser-extensions.mjs';
import { isFromEU } from 'detect-europe-js'; import { isFromEU } from 'detect-europe-js';
import { isFrozenUA } from 'ua-is-frozen'; import { isFrozenUA } from 'ua-is-frozen';
import { isStandalonePWA } from 'is-standalone-pwa'; import { isStandalonePWA } from 'is-standalone-pwa';
const { Crawler } = Extension.BrowserName;
const toResult = (value, head, ext) => typeof value === 'string' ? UAParser(value, head, ext) : value; const toResult = (value, head, ext) => typeof value === 'string' ? UAParser(value, head, ext) : value;
@ -25,8 +24,8 @@ const getDeviceVendor = (model) => UAParser(`Mozilla/5.0 (Linux; Android 10; ${m
const isAppleSilicon = (resultOrUA) => { const isAppleSilicon = (resultOrUA) => {
const res = toResult(resultOrUA); const res = toResult(resultOrUA);
if (res.os.is(OSName.MACOS)) { if (res.os.is(OS.MACOS)) {
if (res.cpu.is(CPUArch.ARM)) { if (res.cpu.is(CPU.ARM)) {
return true; return true;
} }
if (typeof resultOrUA !== 'string' && typeof window !== 'undefined') { if (typeof resultOrUA !== 'string' && typeof window !== 'undefined') {
@ -49,129 +48,88 @@ const isAppleSilicon = (resultOrUA) => {
const isAIBot = (resultOrUA) => [ const isAIBot = (resultOrUA) => [
// AI2 // AI2
Crawler.AI2_BOT, 'ai2bot',
// Amazon // Amazon
Crawler.AMAZON_BOT, 'amazonbot',
// Anthropic // Anthropic
Crawler.ANTHROPIC_AI, 'anthropic-ai',
Crawler.ANTHROPIC_CLAUDE_BOT, 'claude-web',
Crawler.ANTHROPIC_CLAUDE_SEARCHBOT, 'claudebot',
Crawler.ANTHROPIC_CLAUDE_WEB,
// Apple // Apple
Crawler.APPLE_BOT, 'applebot',
Crawler.APPLE_BOT_EXTENDED, 'applebot-extended',
// Brave
Crawler.BRAVE_BOT,
// ByteDance // ByteDance
Crawler.BYTEDANCE_BYTESPIDER, 'bytespider',
Crawler.BYTEDANCE_TIKTOKSPIDER,
// Cohere
Crawler.COHERE_TRAINING_DATA_CRAWLER,
// Common Crawl // Common Crawl
Crawler.COMMON_CRAWL_CCBOT, 'ccbot',
// Coveo
Crawler.COVEO_BOT,
// DataForSeo // DataForSeo
Crawler.DATAFORSEO_BOT, 'dataforseobot',
// DeepSeek
Crawler.DEEPSEEK_BOT,
// Diffbot // Diffbot
Crawler.DIFFBOT, 'diffbot',
// Google // Google
Crawler.GOOGLE_EXTENDED, 'googleother',
Crawler.GOOGLE_OTHER, 'googleother-image',
Crawler.GOOGLE_OTHER_IMAGE, 'googleother-video',
Crawler.GOOGLE_OTHER_VIDEO, 'google-extended',
Crawler.GOOGLE_CLOUDVERTEXBOT,
// Hive AI // Hive AI
Crawler.HIVE_IMAGESIFTBOT, 'imagesiftbot',
// Huawei // Huawei
Crawler.HUAWEI_PETALBOT, 'petalbot',
Crawler.HUAWEI_PANGUBOT,
// Hugging Face
Crawler.HUGGINGFACE_BOT,
// Kangaroo
Crawler.KANGAROO_BOT,
// Mendable.ai
Crawler.FIRECRAWL_AGENT,
// Meta // Meta
Crawler.META_FACEBOOKBOT, 'facebookbot',
Crawler.META_EXTERNALAGENT, 'meta-externalagent',
// OpenAI // OpenAI
Crawler.OPENAI_GPTBOT, 'gptbot',
Crawler.OPENAI_SEARCH_BOT, 'oai-searchbot',
// Perplexity // Perplexity
Crawler.PERPLEXITY_BOT, 'perplexitybot',
// Replicate
Crawler.REPLICATE_BOT,
// Runpod
Crawler.RUNPOD_BOT,
// SB Intuitions
Crawler.SB_INTUITIONS_BOT,
// Semrush // Semrush
Crawler.SEMRUSH_BOT_CONTENTSHAKE, 'semrushbot-ocob',
// Timpi // Timpi
Crawler.TIMPI_BOT, 'timpibot',
// Together AI
Crawler.TOGETHER_BOT,
// Velen.io // Velen.io
Crawler.HUNTER_VELENPUBLICWEBCRAWLER, 'velenpublicwebcrawler',
// Vercel
Crawler.VERCEL_V0BOT,
// Webz.io // Webz.io
Crawler.WEBZIO_OMGILI, 'omgili',
Crawler.WEBZIO_OMGILI_BOT, 'omgilibot',
Crawler.WEBZIO_EXTENDED, 'webzio-extended',
// X
Crawler.XAI_BOT,
// You.com // You.com
Crawler.YOU_BOT, 'youbot',
// Zhipu AI // Zhipu AI
Crawler.ZHIPU_CHATGLM_SPIDER 'chatglm-spider',
]
.map((s) => s.toLowerCase()) // Zyte
.includes(String(toResult(resultOrUA, Crawlers).browser.name).toLowerCase()); 'scrapy'
].includes(String(toResult(resultOrUA, Bots).browser.name).toLowerCase());
const isBot = (resultOrUA) => [ const isBot = (resultOrUA) => [
BrowserType.CLI, 'cli',
BrowserType.CRAWLER, 'crawler',
BrowserType.FETCHER, 'fetcher',
BrowserType.LIBRARY 'library'
].includes(toResult(resultOrUA, Bots).browser.type); ].includes(toResult(resultOrUA, Bots).browser.type);
const isChromeFamily = (resultOrUA) => toResult(resultOrUA).engine.is(EngineName.BLINK); const isChromeFamily = (resultOrUA) => toResult(resultOrUA).engine.is(Engine.BLINK);
const isElectron = () => !!(process?.versions?.hasOwnProperty('electron') || // node.js const isElectron = () => !!(process?.versions?.hasOwnProperty('electron') || // node.js
/ electron\//i.test(navigator?.userAgent)); // browser / electron\//i.test(navigator?.userAgent)); // browser

View File

@ -1,4 +1,4 @@
// Type definitions for UAParser.js v2.0.5 // Type definitions for UAParser.js v2.0.4
// Project: https://github.com/faisalman/ua-parser-js // Project: https://github.com/faisalman/ua-parser-js
// Definitions by: Faisal Salman <https://github.com/faisalman> // Definitions by: Faisal Salman <https://github.com/faisalman>

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
/* UAParser.js v2.0.5 /* UAParser.js v2.0.4
Copyright © 2012-2025 Faisal Salman <f@faisalman.com> Copyright © 2012-2025 Faisal Salman <f@faisalman.com>
AGPLv3 License *//* AGPLv3 License *//*
Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data. Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.
@ -19,7 +19,7 @@
// Constants // Constants
///////////// /////////////
var LIBVERSION = '2.0.5', var LIBVERSION = '2.0.4',
UA_MAX_LENGTH = 500, UA_MAX_LENGTH = 500,
USER_AGENT = 'user-agent', USER_AGENT = 'user-agent',
EMPTY = '', EMPTY = '',

View File

@ -3,7 +3,7 @@
// Source: /src/main/ua-parser.js // Source: /src/main/ua-parser.js
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
/* UAParser.js v2.0.5 /* UAParser.js v2.0.4
Copyright © 2012-2025 Faisal Salman <f@faisalman.com> Copyright © 2012-2025 Faisal Salman <f@faisalman.com>
AGPLv3 License *//* AGPLv3 License *//*
Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data. Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.
@ -21,7 +21,7 @@
// Constants // Constants
///////////// /////////////
var LIBVERSION = '2.0.5', var LIBVERSION = '2.0.4',
UA_MAX_LENGTH = 500, UA_MAX_LENGTH = 500,
USER_AGENT = 'user-agent', USER_AGENT = 'user-agent',
EMPTY = '', EMPTY = '',
@ -459,8 +459,6 @@
], [VERSION, [NAME, 'TikTok'], [TYPE, INAPP]], [ ], [VERSION, [NAME, 'TikTok'], [TYPE, INAPP]], [
/\[(linkedin)app\]/i // LinkedIn App for iOS & Android /\[(linkedin)app\]/i // LinkedIn App for iOS & Android
], [NAME, [TYPE, INAPP]], [ ], [NAME, [TYPE, INAPP]], [
/(zalo(?:app)?)[\/\sa-z]*([\w\.-]+)/i // Zalo
], [[NAME, /(.+)/, 'Zalo'], VERSION, [TYPE, INAPP]], [
/(chromium)[\/ ]([-\w\.]+)/i // Chromium /(chromium)[\/ ]([-\w\.]+)/i // Chromium
], [NAME, VERSION], [ ], [NAME, VERSION], [
@ -542,15 +540,15 @@
/( (ce|mobile); ppc;|\/[\w\.]+arm\b)/i /( (ce|mobile); ppc;|\/[\w\.]+arm\b)/i
], [[ARCHITECTURE, 'arm']], [ ], [[ARCHITECTURE, 'arm']], [
/((ppc|powerpc)(64)?)( mac|;|\))/i // PowerPC
], [[ARCHITECTURE, /ower/, EMPTY, lowerize]], [
/ sun4\w[;\)]/i // SPARC / sun4\w[;\)]/i // SPARC
], [[ARCHITECTURE, '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 // IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC
/\b(avr32|ia64(?=;)|68k(?=\))|\barm(?=v([1-7]|[5-7]1)l?|;|eabi)|(irix|mips|sparc)(64)?\b|pa-risc)/i, ], [[ARCHITECTURE, lowerize]]
/((ppc|powerpc)(64)?)( mac|;|\))/i, // PowerPC
/(?:osf1|[freopnt]{3,4}bsd) (alpha)/i // Alpha
], [[ARCHITECTURE, /ower/, EMPTY, lowerize]], [
/winnt.+\[axp/i
], [[ARCHITECTURE, 'alpha']]
], ],
device : [[ device : [[
@ -774,8 +772,7 @@
/; (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)[_ ]([\w\+ ]+?)(?: bui|\)|; r)/i, // BLU/HMD/IMO/Infinix/Lava/OnePlus/TCL
/(hp) ([\w ]+\w)/i, // HP iPAQ /(hp) ([\w ]+\w)/i, // HP iPAQ
/(microsoft); (lumia[\w ]+)/i, // Microsoft Lumia /(microsoft); (lumia[\w ]+)/i, // Microsoft Lumia
/(oppo) ?([\w ]+) bui/i, // OPPO /(oppo) ?([\w ]+) bui/i // OPPO
/droid[^;]+; (philips)[_ ]([sv-x][\d]{3,4}[xz]?)/i // Philips
], [VENDOR, MODEL, [TYPE, MOBILE]], [ ], [VENDOR, MODEL, [TYPE, MOBILE]], [
/(kobo)\s(ereader|touch)/i, // Kobo /(kobo)\s(ereader|touch)/i, // Kobo
@ -802,7 +799,6 @@
// SMARTTVS // SMARTTVS
/////////////////// ///////////////////
/(philips)[\w ]+tv/i, // Philips
/smart-tv.+(samsung)/i // Samsung /smart-tv.+(samsung)/i // Samsung
], [VENDOR, [TYPE, SMARTTV]], [ ], [VENDOR, [TYPE, SMARTTV]], [
/hbbtv.+maple;(\d+)/i /hbbtv.+maple;(\d+)/i
@ -840,6 +836,11 @@
/\b(roku)[\dx]*[\)\/]((?:dvp-)?[\d\.]*)/i, // Roku /\b(roku)[\dx]*[\)\/]((?:dvp-)?[\d\.]*)/i, // Roku
/hbbtv\/\d+\.\d+\.\d+ +\([\w\+ ]*; *([\w\d][^;]*);([^;]*)/i // HbbTV devices /hbbtv\/\d+\.\d+\.\d+ +\([\w\+ ]*; *([\w\d][^;]*);([^;]*)/i // HbbTV devices
], [[VENDOR, /.+\/(\w+)/, '$1', strMapper, {'LG':'lge'}], [MODEL, trim], [TYPE, SMARTTV]], [ ], [[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 // CONSOLES
@ -886,7 +887,7 @@
/droid.+; (glass) \d/i // Google Glass /droid.+; (glass) \d/i // Google Glass
], [MODEL, [VENDOR, GOOGLE], [TYPE, XR]], [ ], [MODEL, [VENDOR, GOOGLE], [TYPE, XR]], [
/(pico) ([\w ]+) os\d/i // Pico /(pico) (4|neo3(?: link|pro)?)/i // Pico
], [VENDOR, MODEL, [TYPE, XR]], [ ], [VENDOR, MODEL, [TYPE, XR]], [
/(quest( \d| pro)?s?).+vr/i // Meta Quest /(quest( \d| pro)?s?).+vr/i // Meta Quest
], [MODEL, [VENDOR, FACEBOOK], [TYPE, XR]], [ ], [MODEL, [VENDOR, FACEBOOK], [TYPE, XR]], [
@ -910,10 +911,6 @@
// MIXED (GENERIC) // MIXED (GENERIC)
/////////////////// ///////////////////
/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).+?(mobile|vr|\d) safari/i /droid .+?; ([^;]+?)(?: bui|; wv\)|\) applew).+?(mobile|vr|\d) safari/i
], [MODEL, [TYPE, strMapper, { 'mobile' : 'Mobile', 'xr' : 'VR', '*' : TABLET }]], [ ], [MODEL, [TYPE, strMapper, { 'mobile' : 'Mobile', 'xr' : 'VR', '*' : TABLET }]], [
/\b((tablet|tab)[;\/]|focus\/\d(?!.+mobile))/i // Unidentifiable Tablet /\b((tablet|tab)[;\/]|focus\/\d(?!.+mobile))/i // Unidentifiable Tablet
@ -1392,22 +1389,11 @@
extensions = undefined; extensions = undefined;
} }
if (headers) { // Convert Headers object into a plain object
if (typeof headers.append === FUNC_TYPE) { if (headers && typeof headers.append === FUNC_TYPE) {
// Convert Headers object into a plain object var kv = {};
var kv = {}; headers.forEach(function (v, k) { kv[k] = v; });
headers.forEach(function (v, k) { kv[String(k).toLowerCase()] = v; }); headers = kv;
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)) { if (!(this instanceof UAParser)) {

View File

@ -339,6 +339,16 @@
"type" : "fetcher" "type" : "fetcher"
} }
}, },
{
"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" : "fetcher"
}
},
{ {
"desc" : "UptimeRobot", "desc" : "UptimeRobot",
"ua" : "Mozilla/5.0 (compatible; UptimeRobot/2.0; http://www.uptimerobot.com/)", "ua" : "Mozilla/5.0 (compatible; UptimeRobot/2.0; http://www.uptimerobot.com/)",

View File

@ -5,8 +5,6 @@ const traverse = require('@babel/traverse').default;
const safe = require('safe-regex'); const safe = require('safe-regex');
const { UAParser } = require('../../src/main/ua-parser'); const { UAParser } = require('../../src/main/ua-parser');
const { Bots, CLIs, Crawlers, Emails, Fetchers, InApps, Libraries, Vehicles } = require('../../src/extensions/ua-parser-extensions'); 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', () => { describe('Extensions', () => {
[ [
@ -44,29 +42,29 @@ describe('Extensions', () => {
const jsdom = 'Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/20.0.3'; 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)'; const scrapy = 'Scrapy/1.5.0 (+https://scrapy.org)';
assert.equal(UAParser(scrapy, Bots).browser.name, Library.SCRAPY); assert.equal(UAParser(scrapy, Bots).browser.name, 'Scrapy');
const emailParser = new UAParser(Emails); const emailParser = new UAParser(Emails);
assert.deepEqual(emailParser.setUA(outlook).getBrowser(), {name: Email.MICROSOFT_OUTLOOK, version: "16.0.9126", major: "16", type: BrowserType.EMAIL}); assert.deepEqual(emailParser.setUA(outlook).getBrowser(), {name: "Microsoft Outlook", version: "16.0.9126", major: "16", type: "email"});
assert.deepEqual(emailParser.setUA(thunderbird).getBrowser(), {name: Email.THUNDERBIRD, version: "78.13.0", major: "78", type: BrowserType.EMAIL}); assert.deepEqual(emailParser.setUA(thunderbird).getBrowser(), {name: "Thunderbird", version: "78.13.0", major: "78", type: "email"});
const libraryParser = new UAParser(Libraries); const libraryParser = new UAParser(Libraries);
assert.deepEqual(libraryParser.setUA(axios).getBrowser(), {name: Library.AXIOS, version: "1.3.5", major: "1", type: BrowserType.LIBRARY}); assert.deepEqual(libraryParser.setUA(axios).getBrowser(), {name: "axios", version: "1.3.5", major: "1", type: "library"});
assert.deepEqual(libraryParser.setUA(jsdom).getBrowser(), {name: Library.JSDOM, version: "20.0.3", major: "20", type: BrowserType.LIBRARY}); assert.deepEqual(libraryParser.setUA(jsdom).getBrowser(), {name: "jsdom", version: "20.0.3", major: "20", type: "library"});
assert.deepEqual(libraryParser.setUA(scrapy).getBrowser(), {name: Library.SCRAPY, version: "1.5.0", major: "1", type: BrowserType.LIBRARY}); assert.deepEqual(libraryParser.setUA(scrapy).getBrowser(), {name: "Scrapy", version: "1.5.0", major: "1", type: "library"});
// Bluesky // Bluesky
const bluesky = 'Mozilla/5.0 (compatible; Bluesky Cardyb/1.1; +mailto:support@bsky.app)'; const bluesky = 'Mozilla/5.0 (compatible; Bluesky Cardyb/1.1; +mailto:support@bsky.app)';
assert.deepEqual(new UAParser(bluesky, Bots).getBrowser(), { assert.deepEqual(new UAParser(bluesky, Bots).getBrowser(), {
name: Fetcher.BLUESKY, name: 'Bluesky',
version: '1.1', version: '1.1',
major: '1', major: '1',
type: BrowserType.FETCHER type: 'fetcher'
}); });
const whatsapp = "WhatsApp/2.0 A"; const whatsapp = "WhatsApp/2.0 A";
assert.deepEqual(new UAParser(whatsapp, Fetchers).getOS(), { assert.deepEqual(new UAParser(whatsapp, Fetchers).getOS(), {
name : OSName.ANDROID, name : 'Android',
version : undefined version : undefined
}); });
}); });
@ -79,14 +77,14 @@ describe('Merge', () => {
// try merging crawlers & CLIs // try merging crawlers & CLIs
const crawlersAndCLIs = { browser : [...Crawlers.browser, ...CLIs.browser]}; const crawlersAndCLIs = { browser : [...Crawlers.browser, ...CLIs.browser]};
const crawlersAndCLIsParser = new UAParser(crawlersAndCLIs); const crawlersAndCLIsParser = new UAParser(crawlersAndCLIs);
assert.deepEqual(crawlersAndCLIsParser.setUA(wget).getBrowser(), {name: CLI.WGET, version: "1.21.1", major: "1", type: BrowserType.CLI}); assert.deepEqual(crawlersAndCLIsParser.setUA(wget).getBrowser(), {name: "Wget", version: "1.21.1", major: "1", type:"cli"});
assert.deepEqual(crawlersAndCLIsParser.setUA(facebookBot).getBrowser(), {name: Crawler.META_FACEBOOKBOT, version: "1.0", major: "1", type: BrowserType.CRAWLER}); assert.deepEqual(crawlersAndCLIsParser.setUA(facebookBot).getBrowser(), {name: "FacebookBot", version: "1.0", major: "1", type:"crawler"});
// alternative merge options // alternative merge options
const crawlersAndCLIsParser2 = new UAParser([Crawlers, CLIs]); const crawlersAndCLIsParser2 = new UAParser([Crawlers, CLIs]);
const crawlersAndCLIsParser3 = new UAParser(facebookBot, [Crawlers, CLIs]); const crawlersAndCLIsParser3 = new UAParser(facebookBot, [Crawlers, CLIs]);
assert.deepEqual(crawlersAndCLIsParser2.setUA(wget).getBrowser(), {name: CLI.WGET, version: "1.21.1", major: "1", type: BrowserType.CLI}); assert.deepEqual(crawlersAndCLIsParser2.setUA(wget).getBrowser(), {name: "Wget", version: "1.21.1", major: "1", type:"cli"});
assert.deepEqual(crawlersAndCLIsParser3.getBrowser(), {name: Crawler.META_FACEBOOKBOT, version: "1.0", major: "1", type: BrowserType.CRAWLER}); assert.deepEqual(crawlersAndCLIsParser3.getBrowser(), {name: "FacebookBot", version: "1.0", major: "1", type:"crawler"});
}); });
}); });

View File

@ -2,7 +2,6 @@ const assert = require('assert');
const { UAParser } = require('../../src/main/ua-parser'); const { UAParser } = require('../../src/main/ua-parser');
const { getDeviceVendor, isAppleSilicon, isAIBot, isBot, isChromeFamily } = require('../../src/helpers/ua-parser-helpers'); const { getDeviceVendor, isAppleSilicon, isAIBot, isBot, isChromeFamily } = require('../../src/helpers/ua-parser-helpers');
const { Bots, Emails } = require('../../src/extensions/ua-parser-extensions'); const { Bots, Emails } = require('../../src/extensions/ua-parser-extensions');
const { DeviceVendor } = require('../../src/enums/ua-parser-enums');
describe('getDeviceVendor', () => { describe('getDeviceVendor', () => {
it('Can guess the device vendor from a model name', () => { it('Can guess the device vendor from a model name', () => {
@ -12,10 +11,10 @@ describe('getDeviceVendor', () => {
const modelNexus = 'Nexus 6P'; const modelNexus = 'Nexus 6P';
const modelAquos = 'AQUOS-TVX19B'; const modelAquos = 'AQUOS-TVX19B';
assert.equal(getDeviceVendor(modelSM), DeviceVendor.SAMSUNG); assert.equal(getDeviceVendor(modelSM), 'Samsung');
assert.equal(getDeviceVendor(modelRedmi), DeviceVendor.XIAOMI); assert.equal(getDeviceVendor(modelRedmi), 'Xiaomi');
assert.equal(getDeviceVendor(modelNexus), DeviceVendor.HUAWEI); assert.equal(getDeviceVendor(modelNexus), 'Huawei');
assert.equal(getDeviceVendor(modelAquos), DeviceVendor.SHARP); assert.equal(getDeviceVendor(modelAquos), 'Sharp');
}); });
}); });

View File

@ -1,6 +1,5 @@
const assert = require('assert'); const assert = require('assert');
const { UAParser } = require('../../src/main/ua-parser'); 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'); const UACHTests = require('../data/ua-ch/headers');
describe('Map UA-CH headers', () => { describe('Map UA-CH headers', () => {
@ -27,27 +26,27 @@ describe('Map UA-CH headers', () => {
it('Can read from client-hints headers using `withClientHints()`', () => { 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.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, BrowserName.CHROME); assert.strictEqual(uap.browser.name, "Chrome");
assert.strictEqual(uap.browser.version, "93.0.1.2"); assert.strictEqual(uap.browser.version, "93.0.1.2");
assert.strictEqual(uap.browser.major, "93"); assert.strictEqual(uap.browser.major, "93");
assert.strictEqual(browser.name, BrowserName.CHROME); assert.strictEqual(browser.name, "Chrome");
assert.strictEqual(browser.version, "93.0.1.2"); assert.strictEqual(browser.version, "93.0.1.2");
assert.strictEqual(browser.major, "93"); assert.strictEqual(browser.major, "93");
assert.strictEqual(uap.cpu.architecture, CPUArch.ARM_64); assert.strictEqual(uap.cpu.architecture, "arm64");
assert.strictEqual(cpu.architecture, CPUArch.ARM_64); assert.strictEqual(cpu.architecture, "arm64");
assert.strictEqual(uap.device.type, DeviceType.MOBILE); assert.strictEqual(uap.device.type, "mobile");
assert.strictEqual(uap.device.model, "Pixel 99"); assert.strictEqual(uap.device.model, "Pixel 99");
assert.strictEqual(uap.device.vendor, DeviceVendor.GOOGLE); assert.strictEqual(uap.device.vendor, "Google");
assert.strictEqual(device.type, DeviceType.MOBILE); assert.strictEqual(device.type, "mobile");
assert.strictEqual(device.model, "Pixel 99"); assert.strictEqual(device.model, "Pixel 99");
assert.strictEqual(device.vendor, DeviceVendor.GOOGLE); assert.strictEqual(device.vendor, "Google");
assert.strictEqual(uap.engine.name, EngineName.BLINK); assert.strictEqual(uap.engine.name, 'Blink');
assert.strictEqual(uap.engine.version, '93.0.1.2'); assert.strictEqual(uap.engine.version, '93.0.1.2');
assert.strictEqual(engine.name, EngineName.BLINK); assert.strictEqual(engine.name, 'Blink');
assert.strictEqual(engine.version, '93.0.1.2'); assert.strictEqual(engine.version, '93.0.1.2');
assert.strictEqual(uap.os.name, OSName.WINDOWS); assert.strictEqual(uap.os.name, "Windows");
assert.strictEqual(uap.os.version, "11"); assert.strictEqual(uap.os.version, "11");
assert.strictEqual(os.name, OSName.WINDOWS); assert.strictEqual(os.name, "Windows");
assert.strictEqual(os.version, "11"); assert.strictEqual(os.version, "11");
}); });
@ -60,16 +59,16 @@ describe('Map UA-CH headers', () => {
engine = new UAParser(headers).getEngine(); engine = new UAParser(headers).getEngine();
os = new UAParser(headers).getOS(); os = new UAParser(headers).getOS();
assert.strictEqual(uap.browser.name, BrowserName.CHROME); assert.strictEqual(uap.browser.name, "Chrome");
assert.strictEqual(uap.browser.version, "110.0.0.0"); assert.strictEqual(uap.browser.version, "110.0.0.0");
assert.strictEqual(uap.browser.major, "110"); assert.strictEqual(uap.browser.major, "110");
assert.strictEqual(uap.cpu.architecture, CPUArch.X86_64); assert.strictEqual(uap.cpu.architecture, "amd64");
assert.strictEqual(uap.device.type, undefined); assert.strictEqual(uap.device.type, undefined);
assert.strictEqual(uap.device.model, undefined); assert.strictEqual(uap.device.model, undefined);
assert.strictEqual(uap.device.vendor, undefined); assert.strictEqual(uap.device.vendor, undefined);
assert.strictEqual(uap.engine.name, EngineName.BLINK); assert.strictEqual(uap.engine.name, 'Blink');
assert.strictEqual(uap.engine.version, '110.0.0.0'); assert.strictEqual(uap.engine.version, '110.0.0.0');
assert.strictEqual(uap.os.name, OSName.LINUX); assert.strictEqual(uap.os.name, "Linux");
assert.strictEqual(uap.os.version, undefined); assert.strictEqual(uap.os.version, undefined);
}); });
@ -82,16 +81,16 @@ describe('Map UA-CH headers', () => {
uap = UAParser(headers2).withClientHints(); uap = UAParser(headers2).withClientHints();
assert.strictEqual(uap.browser.name, BrowserName.CHROME); assert.strictEqual(uap.browser.name, "Chrome");
assert.strictEqual(uap.browser.version, "110.0.0.0"); assert.strictEqual(uap.browser.version, "110.0.0.0");
assert.strictEqual(uap.browser.major, "110"); assert.strictEqual(uap.browser.major, "110");
assert.strictEqual(uap.cpu.architecture, CPUArch.X86_64); assert.strictEqual(uap.cpu.architecture, "amd64");
assert.strictEqual(uap.device.type, DeviceType.MOBILE); assert.strictEqual(uap.device.type, "mobile");
assert.strictEqual(uap.device.model, undefined); assert.strictEqual(uap.device.model, undefined);
assert.strictEqual(uap.device.vendor, undefined); assert.strictEqual(uap.device.vendor, undefined);
assert.strictEqual(uap.engine.name, EngineName.BLINK); assert.strictEqual(uap.engine.name, 'Blink');
assert.strictEqual(uap.engine.version, '110.0.0.0'); assert.strictEqual(uap.engine.version, '110.0.0.0');
assert.strictEqual(uap.os.name, OSName.LINUX); assert.strictEqual(uap.os.name, "Linux");
assert.strictEqual(uap.os.version, undefined); assert.strictEqual(uap.os.version, undefined);
}); });
@ -118,10 +117,10 @@ describe('Map UA-CH headers', () => {
} }
*/ */
assert.strictEqual(ua.os.is(OSName.MACOS), true); assert.strictEqual(ua.os.is("macOS"), true);
assert.strictEqual(ua.cpu.is(CPUArch.ARM), true); assert.strictEqual(ua.cpu.is("arm"), true);
assert.strictEqual(ua.device.is(DeviceType.MOBILE), false); assert.strictEqual(ua.device.is("mobile"), false);
assert.strictEqual(ua.device.is(DeviceType.TABLET), false); assert.strictEqual(ua.device.is("tablet"), false);
}); });
}); });
@ -140,11 +139,11 @@ describe('Map UA-CH headers', () => {
}; };
UAParser(FFVR).withClientHints().then(ua => { UAParser(FFVR).withClientHints().then(ua => {
assert.strictEqual(ua.device.type, DeviceType.XR); assert.strictEqual(ua.device.type, 'xr');
}); });
UAParser(FFEInk).withClientHints().then(ua => { UAParser(FFEInk).withClientHints().then(ua => {
assert.strictEqual(ua.device.type, DeviceType.TABLET); assert.strictEqual(ua.device.type, 'tablet');
}); });
@ -170,7 +169,7 @@ describe('Map UA-CH headers', () => {
uap = UAParser(headers2).withClientHints(); uap = UAParser(headers2).withClientHints();
assert.strictEqual(uap.browser.name, BrowserName.CHROME); assert.strictEqual(uap.browser.name, "Chrome");
assert.strictEqual(uap.browser.version, undefined); assert.strictEqual(uap.browser.version, undefined);
assert.strictEqual(uap.browser.major, undefined); assert.strictEqual(uap.browser.major, undefined);
}); });
@ -197,27 +196,27 @@ describe('Map UA-CH headers', () => {
}; };
uap = UAParser(headers3a).withClientHints(); uap = UAParser(headers3a).withClientHints();
assert.strictEqual(uap.browser.name, BrowserName.CHROME); assert.strictEqual(uap.browser.name, "Chrome");
assert.strictEqual(uap.browser.version, "120.0.6099.132"); assert.strictEqual(uap.browser.version, "120.0.6099.132");
uap = UAParser(headers3b).withClientHints(); uap = UAParser(headers3b).withClientHints();
assert.strictEqual(uap.browser.name, BrowserName.CHROME); assert.strictEqual(uap.browser.name, "Chrome");
assert.strictEqual(uap.browser.version, "120.0.6099.132"); assert.strictEqual(uap.browser.version, "120.0.6099.132");
uap = UAParser(headers3c).withClientHints(); uap = UAParser(headers3c).withClientHints();
assert.strictEqual(uap.browser.name, BrowserName.CHROME); assert.strictEqual(uap.browser.name, "Chrome");
assert.strictEqual(uap.browser.version, "120.0.6099.132"); assert.strictEqual(uap.browser.version, "120.0.6099.132");
uap = UAParser(headers3d).withClientHints(); uap = UAParser(headers3d).withClientHints();
assert.strictEqual(uap.browser.name, BrowserName.EDGE); assert.strictEqual(uap.browser.name, "Edge");
assert.strictEqual(uap.browser.version, "120.0.6099.133"); assert.strictEqual(uap.browser.version, "120.0.6099.133");
uap = UAParser(headers3e).withClientHints(); uap = UAParser(headers3e).withClientHints();
assert.strictEqual(uap.browser.name, BrowserName.EDGE); assert.strictEqual(uap.browser.name, "Edge");
assert.strictEqual(uap.browser.version, "120.0.6099.133"); assert.strictEqual(uap.browser.version, "120.0.6099.133");
uap = UAParser(headers3f).withClientHints(); uap = UAParser(headers3f).withClientHints();
assert.strictEqual(uap.browser.name, BrowserName.EDGE); assert.strictEqual(uap.browser.name, "Edge");
assert.strictEqual(uap.browser.version, "120.0.6099.133"); assert.strictEqual(uap.browser.version, "120.0.6099.133");
}); });
}); });
@ -236,169 +235,169 @@ describe('Identify vendor & type of device from given model name', () => {
{ {
model: '220733SG', model: '220733SG',
expect: { expect: {
vendor : DeviceVendor.XIAOMI, vendor : 'Xiaomi',
type : DeviceType.MOBILE type : 'mobile'
} }
}, },
{ {
model: '5087Z', model: '5087Z',
expect: { expect: {
vendor : DeviceVendor.TCL, vendor : 'TCL',
type : DeviceType.MOBILE type : 'mobile'
} }
}, },
{ {
model: '9137W', model: '9137W',
expect: { expect: {
vendor : DeviceVendor.TCL, vendor : 'TCL',
type : DeviceType.TABLET type : 'tablet'
} }
}, },
{ {
model: 'BE2015', model: 'BE2015',
expect: { expect: {
vendor : DeviceVendor.ONEPLUS, vendor : 'OnePlus',
type : DeviceType.MOBILE type : 'mobile'
} }
}, },
{ {
model: 'CPH2389', model: 'CPH2389',
expect: { expect: {
vendor : DeviceVendor.ONEPLUS, vendor : 'OnePlus',
type : DeviceType.MOBILE type : 'mobile'
} }
}, },
{ {
model: 'Infinix X669C', model: 'Infinix X669C',
expect: { expect: {
vendor : DeviceVendor.INFINIX, vendor : 'Infinix',
type : DeviceType.MOBILE type : 'mobile'
} }
}, },
{ {
model: 'itel L6502', model: 'itel L6502',
expect: { expect: {
vendor : DeviceVendor.ITEL, vendor : 'itel',
type : DeviceType.MOBILE type : 'mobile'
} }
}, },
{ {
model: 'Lenovo TB-X606F', model: 'Lenovo TB-X606F',
expect: { expect: {
vendor : DeviceVendor.LENOVO, vendor : 'Lenovo',
type : DeviceType.TABLET type : 'tablet'
} }
}, },
{ {
model: 'LM-Q720', model: 'LM-Q720',
expect: { expect: {
vendor : DeviceVendor.LG, vendor : 'LG',
type : DeviceType.MOBILE type : 'mobile'
} }
}, },
{ {
model: 'M2003J15SC', model: 'M2003J15SC',
expect: { expect: {
vendor : DeviceVendor.XIAOMI, vendor : 'Xiaomi',
type : DeviceType.MOBILE type : 'mobile'
} }
}, },
{ {
model: 'MAR-LX1A', model: 'MAR-LX1A',
expect: { expect: {
vendor : DeviceVendor.HUAWEI, vendor : 'Huawei',
type : DeviceType.MOBILE type : 'mobile'
} }
}, },
{ {
model: 'moto g(20)', model: 'moto g(20)',
expect: { expect: {
vendor : DeviceVendor.MOTOROLA, vendor : 'Motorola',
type : DeviceType.MOBILE type : 'mobile'
} }
}, },
{ {
model: 'Nokia C210', model: 'Nokia C210',
expect: { expect: {
vendor : DeviceVendor.NOKIA, vendor : 'Nokia',
type : DeviceType.MOBILE type : 'mobile'
} }
}, },
{ {
model: 'Pixel 8', model: 'Pixel 8',
expect: { expect: {
vendor : DeviceVendor.GOOGLE, vendor : 'Google',
type : DeviceType.MOBILE type : 'mobile'
} }
}, },
{ {
model: 'Redmi Note 9S', model: 'Redmi Note 9S',
expect: { expect: {
vendor : DeviceVendor.XIAOMI, vendor : 'Xiaomi',
type : DeviceType.MOBILE type : 'mobile'
} }
}, },
{ {
model: 'RMX3830', model: 'RMX3830',
expect: { expect: {
vendor : DeviceVendor.REALME, vendor : 'Realme',
type : DeviceType.MOBILE type : 'mobile'
} }
}, },
{ {
model: 'SM-S536DL', model: 'SM-S536DL',
expect: { expect: {
vendor : DeviceVendor.SAMSUNG, vendor : 'Samsung',
type : DeviceType.MOBILE type : 'mobile'
} }
}, },
{ {
model: 'SM-S546VL', model: 'SM-S546VL',
expect: { expect: {
vendor : DeviceVendor.SAMSUNG, vendor : 'Samsung',
type : DeviceType.MOBILE type : 'mobile'
} }
}, },
{ {
model: 'SM-T875', model: 'SM-T875',
expect: { expect: {
vendor : DeviceVendor.SAMSUNG, vendor : 'Samsung',
type : DeviceType.TABLET type : 'tablet'
} }
}, },
{ {
model: 'STK-L21', model: 'STK-L21',
expect: { expect: {
vendor : DeviceVendor.HUAWEI, vendor : 'Huawei',
type : DeviceType.MOBILE type : 'mobile'
} }
}, },
{ {
model: 'T430W', model: 'T430W',
expect: { expect: {
vendor : DeviceVendor.TCL, vendor : 'TCL',
type : DeviceType.MOBILE type : 'mobile'
} }
}, },
{ {
model: 'TECNO KI5k', model: 'TECNO KI5k',
expect: { expect: {
vendor : DeviceVendor.TECNO, vendor : 'TECNO',
type : DeviceType.MOBILE type : 'mobile'
} }
}, },
{ {
model: 'vivo 1820', model: 'vivo 1820',
expect: { expect: {
vendor : DeviceVendor.VIVO, vendor : 'Vivo',
type : DeviceType.MOBILE type : 'mobile'
} }
}, },
{ {
model: 'Xbox', model: 'Xbox',
expect: { expect: {
vendor : DeviceVendor.MICROSOFT, vendor : 'Microsoft',
type : DeviceType.CONSOLE type : 'console'
} }
} }
] ]