Compare commits

..

19 Commits

Author SHA1 Message Date
Faisal Salman
e006e5a129 Merge tag 'tags/2.0.0' into pro-enterprise 2024-11-21 17:40:24 +07:00
Faisal Salman
38baf844fc Update version to 2.0.0 2024-11-18 07:55:18 +07:00
Faisal Salman
70b3003344 [submodule:helpers] Add new method isAIBot(): detect AI bots 2024-11-16 22:14:14 +07:00
Faisal Salman
5b375b90d5 [submodule:helpers] Enable directly pass user-agent as an input to isAppleSilicon() / isBot() / isChromeFamily() 2024-11-16 21:23:39 +07:00
Faisal Salman
b1c7dfcc3a [submodule:helpers] Revert providing extra param in isAppleSilicon() and just check for window instead 2024-11-16 19:22:43 +07:00
Faisal Salman
2b125c8de4 [submodule:extensions] Add new bots: AI2Bot, aiHitBot, anthropic-ai, cohere-ai, Diffbot, ImagesiftBot, magpie-crawler, Omgilibot, Screaming Frog SEO Spider, Seznambot, Teoma, Timpibot, VelenPublicWebCrawler, Vercelbot, Webzio-Extended, YouBot 2024-11-16 18:40:02 +07:00
Faisal Salman
2181559b01 [submodule:extensions] Add new email: Airmail, BlueMail, eMClient, NaverMailApp, Sparrow, Yahoo 2024-11-16 15:28:35 +07:00
Faisal Salman
14caf6d204 [submodule:extensions] Add new library: java, python-urllib, python-requests 2024-11-15 17:25:43 +07:00
Faisal Salman
4a12562946 [submodule:extensions] Add new CLI: ELinks, HTTPie 2024-11-14 22:51:41 +07:00
Faisal Salman
fdcb01d64e Fix typos 2024-11-14 20:30:12 +07:00
Faisal Salman
b960c42691 Make it prize - 2.0.0-rc.3 2024-11-14 20:24:40 +07:00
Faisal Salman
abde14f2a5 Make it biz - 2.0.0-rc.3 2024-11-14 20:11:17 +07:00
Faisal Salman
d50be39f3b Update 2.0.0-beta.3-pro-enterprise
Fix #735
2024-07-24 13:53:42 +07:00
Faisal Salman
44d9d5700f Update 2.0.0-beta.3-pro-business 2024-07-24 13:48:45 +07:00
Faisal Salman
10ec6349e2 Make it prize - 2.0.0-beta.2 2024-02-01 12:13:08 +07:00
Faisal Salman
23dc320be4 Make it biz - 2.0.0-beta.2 2024-02-01 12:08:38 +07:00
Faisal Salman
8852b03739 Make it personal 2024-02-01 11:45:23 +07:00
Faisal Salman
f9ac3566cb Make it prize 2023-10-05 22:54:22 +07:00
Faisal Salman
1d776d469b Make it biz 2023-10-05 22:08:02 +07:00
24 changed files with 1206 additions and 1166 deletions

View File

@@ -55,7 +55,8 @@
- **`'ua-parser-js/helpers'`**: Provides utility methods to extend detection functionality:
- `getDeviceVendor()`: Guesses the device vendor based on its model name
- `isAppleSilicon()`: Detects Apple Silicon device properties
- `isBot()`: Checks if the browser is a bot
- `isAIBot()`: Checks if the user-agent is an AI bot
- `isBot()`: Checks if the user-agent is a bot
- `isChromeFamily()`: Checks if the browser is Chrome-based (uses Blink engine) — e.g., New Opera, New Edge, Vivaldi, Brave, Arc, etc.
- `isElectron()`: Detects if current window is running within Electron
- `isFromEU()`: Detects if current browser's timezone is from an EU country
@@ -64,6 +65,17 @@
---
## Version 2.0.0
- `ua-parser-js/extensions` submodule:
- Add new CLI: ELinks, HTTPie
- Add new crawler: AI2Bot, aiHitBot, anthropic-ai, Diffbot, ImagesiftBot, magpie-crawler, Omgilibot, Screaming Frog SEO Spider, Seznambot, Teoma, Timpibot, VelenPublicWebCrawler, Webzio-Extended, YouBot
- Add new email: Airmail, BlueMail, eMClient, NaverMailApp, Sparrow, Yahoo
- Add new fetcher: cohere-ai, Vercelbot
- Add new library: java, python-urllib, python-requests
- `ua-parser-js/helpers` submodule:
- Add new method `isAIBot()`: Checks if the user-agent is an AI bot
## Version 2.0.0-rc.3
- Add support for Headers object

View File

@@ -1,4 +1,4 @@
# UAPARSER.JS PRO PERSONAL LICENSE
# UAPARSER.JS PRO ENTERPRISE 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 who is responsible for purchasing this license.
"You" are the individual, organization, or company who is responsible for purchasing this license.
"The Code" is UAParser.js.
@@ -24,27 +24,25 @@ 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 personal, limited, non-exclusive, non-transferable, non-sublicensable, royalty-free right to use, copy, and modify The Code.
We grant You (and only You) a 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 and cannot be transferred to another individual or organization.
This license is only valid for You as one (1) individual, organization, or company and cannot be transferred to another individual, organization, or company.
---
## Rights
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 may use, copy, and modify The Code for an indefinite number of Projects.
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.
You have the right to receive lifetime updates and one (1) year of support, starting from the time you make the purchase.
---
## Restrictions
You may not use or modify The Code in such a way that it may be used directly for commercial purposes.
You may not redistribute The Code, as-is or modified, except as a part of a Project that you made.
You may not redistribute The Code, as-is or modified, except as a part of a Project that you made for yourself.
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 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.
@@ -54,7 +52,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.

View File

@@ -1,23 +1,29 @@
<p align="center">
<a href="https://uaparser.dev"><img src="https://raw.githubusercontent.com/faisalman/ua-parser-js/gh-pages/images/uap-header.png"></a>
</p>
# UAParser.js PRO Enterprise License
# UAParser.js
Thank you for choosing the UAParser.js PRO Enterprise License.
Thank you for purchasing UAParser.js PRO Personal License, if you haven't please oreder here: https://store.faisalman.com
Please be aware that using this package without a valid license purchase is strictly prohibited and constitutes a violation of applicable copyright laws.
An exception applies if the package is used solely as a part of a product developed by a valid license holder, in accordance with their license terms.
If you have not yet purchased a license, you may do so at https://store.faisalman.com.
# Download
```sh
npm install @ua-parser-js/pro-personal
npm install @ua-parser-js/pro-enterprise
```
# Documentation
https://docs.uaparser.dev
```js
import { UAParser } from '@ua-parser-js/pro-enterprise';
```
# License
UAParser.js PRO Personal
UAParser.js PRO Enterprise
Copyright (c) 2012-2024 Faisal Salman <<f@faisalman.com>>
Copyright (c) 2023-2024 Faisal Salman <<f@faisalman.com>>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1658
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
{
"title": "UAParser.js PRO Personal",
"name": "@ua-parser-js/pro-personal",
"version": "2.0.0-rc.3",
"title": "UAParser.js PRO Enterprise",
"name": "@ua-parser-js/pro-enterprise",
"version": "2.0.0",
"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": [
@@ -180,7 +180,8 @@
},
"./enums": {
"require": "./src/enums/ua-parser-enums.js",
"import": "./src/enums/ua-parser-enums.mjs"
"import": "./src/enums/ua-parser-enums.mjs",
"types": "./src/enums/ua-parser-enums.d.ts"
},
"./extensions": {
"require": "./src/extensions/ua-parser-extensions.js",

View File

@@ -1,8 +1,8 @@
///////////////////////////////////////////////
/* Enums for UAParser.js v2.0.0-rc.3
/* Enums for UAParser.js v2.0.0
https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com>
UAParser.js PRO Personal License */
UAParser.js PRO Enterprise License */
//////////////////////////////////////////////
/*jshint esversion: 6 */

View File

@@ -3,10 +3,10 @@
// Source: /src/enums/ua-parser-enums.js
///////////////////////////////////////////////
/* Enums for UAParser.js v2.0.0-rc.3
/* Enums for UAParser.js v2.0.0
https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com>
UAParser.js PRO Personal License */
UAParser.js PRO Enterprise License */
//////////////////////////////////////////////
/*jshint esversion: 6 */

View File

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

View File

@@ -1,8 +1,8 @@
///////////////////////////////////////////////
/* Extensions for UAParser.js v2.0.0-rc.3
/* Extensions for UAParser.js v2.0.0
https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com>
UAParser.js PRO Personal License */
UAParser.js PRO Enterprise License */
//////////////////////////////////////////////
/*jshint esversion: 6 */
@@ -28,8 +28,8 @@ const LIBRARY = 'library';
const CLIs = Object.freeze({
browser : [
// wget / curl / lynx
[/(wget|curl|lynx)[\/ ]([\w\.]+)/i], [NAME, VERSION, [TYPE, CLI]]
// wget / curl / Lynx / ELinks / HTTPie
[/(wget|curl|lynx|elinks|httpie)[\/ ]\(?([\w\.-]+)/i], [NAME, VERSION, [TYPE, CLI]]
]
});
@@ -42,7 +42,6 @@ const Crawlers = Object.freeze({
[
// AhrefsBot - https://ahrefs.com/robot
// Amazonbot - https://developer.amazon.com/amazonbot
// Applebot - http://apple.com/go/applebot
// Bingbot - http://www.bing.com/bingbot.htm
// CCBot - https://commoncrawl.org/faq
// Dotbot - https://moz.com/help/moz-procedures/crawlers/dotbot
@@ -54,13 +53,17 @@ const Crawlers = Object.freeze({
// OpenAI's SearchGPT - https://platform.openai.com/docs/bots
// PerplexityBot - https://perplexity.ai/perplexitybot
// SemrushBot - http://www.semrush.com/bot.html
/((?:ahrefs|amazon|apple|bing|cc|dot|duckduck|exa|facebook|gpt|mj12|mojeek|oai-search|perplexity|semrush)bot)\/([\w\.]+)/i,
// SeznamBot - http://napoveda.seznam.cz/seznambot-intro
/((?:ahrefs|amazon|bing|cc|dot|duckduck|exa|facebook|gpt|mj12|mojeek|oai-search|perplexity|semrush|seznam)bot)\/([\w\.-]+)/i,
// Applebot - http://apple.com/go/applebot
/(applebot(?:-extended)?)\/([\w\.]+)/i,
// Baiduspider https://help.baidu.com/question?prod_id=99&class=0&id=3001
/(baiduspider)[-imagevdonsfcpr]{0,6}\/([\w\.]+)/i,
// ClaudeBot (Anthropic)
/(claude(?:bot|-web))\/([\w\.]+)/i,
/(claude(?:bot|-web)|anthropic-ai)\/?([\w\.]*)/i,
// Coc Coc Bot - https://help.coccoc.com/en/search-engine
/(coccocbot-(?:image|web))\/([\w\.]+)/i,
@@ -87,8 +90,8 @@ const Crawlers = Object.freeze({
// Yeti (Naver)
/(yeti)\/([\w\.]+)/i,
// YisouSpider
/(yisouspider)\/?([\w\.]*)/i
// aiHitBot / Diffbot / Magpie-Crawler / Omgilibot / Webzio-Extended / Screaming Frog SEO Spider / Timpibot / VelenPublicWebCrawler / YisouSpider / YouBot
/((?:aihit|diff|timpi|you)bot|omgili(?:bot)?|(?:magpie-|velenpublicweb)crawler|webzio-extended|(?:screaming frog seo |yisou)spider)\/?([\w\.]*)/i
],
[NAME, VERSION, [TYPE, CRAWLER]],
@@ -97,13 +100,15 @@ const Crawlers = Object.freeze({
// 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
// TurnitinBot - https://www.turnitin.com/robot/crawlerinfo.html
// Yahoo! Slurp - http://help.yahoo.com/help/us/ysearch/slurp
/(360spider-?(?:image|video)?|bytespider|(?:aspiegel|dataforseo|petal|turnitin)bot|(?=yahoo! )slurp)/i
/\b(360spider-?(?:image|video)?|bytespider|(?:ai2|aspiegel|dataforseo|imagesift|petal|turnitin)bot|teoma|(?=yahoo! )slurp)/i
],
[NAME, [TYPE, CRAWLER]]
]
@@ -195,8 +200,10 @@ const ExtraDevices = Object.freeze({
const Emails = Object.freeze({
browser : [
[
// Evolution / Kontact/KMail / [Microsoft/Mac] Outlook / Thunderbird
[/(evolution|kmail2?|kontact|(?:microsoft |mac)outlook|thunderbird)[\s\/]([\w\.]+)/i], [NAME, VERSION, [TYPE, EMAIL]]
/(airmail|bluemail|emclient|evolution|foxmail|kmail2?|kontact|(?:microsoft |mac)?outlook(?:-express)?|navermailapp|(?!chrom.+)sparrow|thunderbird|yahoo)(?:m.+ail; |[\/ ])([\w\.]+)/i
], [NAME, VERSION, [TYPE, EMAIL]]
]
});
@@ -234,8 +241,8 @@ const Fetchers = Object.freeze({
],
[NAME, VERSION, [TYPE, FETCHER]],
// Google Bots / Snapchat
[/(feedfetcher-google|google(?:-read-aloud|producer)|(?=bot; )snapchat)/i],
// Google Bots / Cohere / Snapchat / Vercelbot
[/(cohere-ai|vercelbot|feedfetcher-google|google(?:-read-aloud|producer)|(?=bot; )snapchat)/i],
[NAME, [TYPE, FETCHER]],
]
});
@@ -293,8 +300,6 @@ const MediaPlayers = Object.freeze({
], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [
/(htc streaming player)\s[\w_]+\s\/\s([\d\.]+)/i, // HTC Streaming Player
/(java|python-urllib|python-requests|wget|libcurl)\/([\w\.-_]+)/i,
// Java/urllib/requests/wget/cURL
/(lavf)([\d\.]+)/i // Lavf (FFMPEG)
], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [
@@ -370,8 +375,8 @@ const MediaPlayers = Object.freeze({
const Libraries = Object.freeze({
browser : [
// Axios/jsdom/Scrapy
[/\b(axios|jsdom|scrapy)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, LIBRARY]]
// Axios/jsdom/Scrapy/Java/urllib/requests
[/\b(axios|jsdom|scrapy|java|python-urllib|python-requests)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, LIBRARY]]
]
});

View File

@@ -3,10 +3,10 @@
// Source: /src/extensions/ua-parser-extensions.js
///////////////////////////////////////////////
/* Extensions for UAParser.js v2.0.0-rc.3
/* Extensions for UAParser.js v2.0.0
https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com>
UAParser.js PRO Personal License */
UAParser.js PRO Enterprise License */
//////////////////////////////////////////////
/*jshint esversion: 6 */
@@ -32,8 +32,8 @@ const LIBRARY = 'library';
const CLIs = Object.freeze({
browser : [
// wget / curl / lynx
[/(wget|curl|lynx)[\/ ]([\w\.]+)/i], [NAME, VERSION, [TYPE, CLI]]
// wget / curl / Lynx / ELinks / HTTPie
[/(wget|curl|lynx|elinks|httpie)[\/ ]\(?([\w\.-]+)/i], [NAME, VERSION, [TYPE, CLI]]
]
});
@@ -46,7 +46,6 @@ const Crawlers = Object.freeze({
[
// AhrefsBot - https://ahrefs.com/robot
// Amazonbot - https://developer.amazon.com/amazonbot
// Applebot - http://apple.com/go/applebot
// Bingbot - http://www.bing.com/bingbot.htm
// CCBot - https://commoncrawl.org/faq
// Dotbot - https://moz.com/help/moz-procedures/crawlers/dotbot
@@ -58,13 +57,17 @@ const Crawlers = Object.freeze({
// OpenAI's SearchGPT - https://platform.openai.com/docs/bots
// PerplexityBot - https://perplexity.ai/perplexitybot
// SemrushBot - http://www.semrush.com/bot.html
/((?:ahrefs|amazon|apple|bing|cc|dot|duckduck|exa|facebook|gpt|mj12|mojeek|oai-search|perplexity|semrush)bot)\/([\w\.]+)/i,
// SeznamBot - http://napoveda.seznam.cz/seznambot-intro
/((?:ahrefs|amazon|bing|cc|dot|duckduck|exa|facebook|gpt|mj12|mojeek|oai-search|perplexity|semrush|seznam)bot)\/([\w\.-]+)/i,
// Applebot - http://apple.com/go/applebot
/(applebot(?:-extended)?)\/([\w\.]+)/i,
// Baiduspider https://help.baidu.com/question?prod_id=99&class=0&id=3001
/(baiduspider)[-imagevdonsfcpr]{0,6}\/([\w\.]+)/i,
// ClaudeBot (Anthropic)
/(claude(?:bot|-web))\/([\w\.]+)/i,
/(claude(?:bot|-web)|anthropic-ai)\/?([\w\.]*)/i,
// Coc Coc Bot - https://help.coccoc.com/en/search-engine
/(coccocbot-(?:image|web))\/([\w\.]+)/i,
@@ -91,8 +94,8 @@ const Crawlers = Object.freeze({
// Yeti (Naver)
/(yeti)\/([\w\.]+)/i,
// YisouSpider
/(yisouspider)\/?([\w\.]*)/i
// aiHitBot / Diffbot / Magpie-Crawler / Omgilibot / Webzio-Extended / Screaming Frog SEO Spider / Timpibot / VelenPublicWebCrawler / YisouSpider / YouBot
/((?:aihit|diff|timpi|you)bot|omgili(?:bot)?|(?:magpie-|velenpublicweb)crawler|webzio-extended|(?:screaming frog seo |yisou)spider)\/?([\w\.]*)/i
],
[NAME, VERSION, [TYPE, CRAWLER]],
@@ -101,13 +104,15 @@ const Crawlers = Object.freeze({
// 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
// TurnitinBot - https://www.turnitin.com/robot/crawlerinfo.html
// Yahoo! Slurp - http://help.yahoo.com/help/us/ysearch/slurp
/(360spider-?(?:image|video)?|bytespider|(?:aspiegel|dataforseo|petal|turnitin)bot|(?=yahoo! )slurp)/i
/\b(360spider-?(?:image|video)?|bytespider|(?:ai2|aspiegel|dataforseo|imagesift|petal|turnitin)bot|teoma|(?=yahoo! )slurp)/i
],
[NAME, [TYPE, CRAWLER]]
]
@@ -199,8 +204,10 @@ const ExtraDevices = Object.freeze({
const Emails = Object.freeze({
browser : [
[
// Evolution / Kontact/KMail / [Microsoft/Mac] Outlook / Thunderbird
[/(evolution|kmail2?|kontact|(?:microsoft |mac)outlook|thunderbird)[\s\/]([\w\.]+)/i], [NAME, VERSION, [TYPE, EMAIL]]
/(airmail|bluemail|emclient|evolution|foxmail|kmail2?|kontact|(?:microsoft |mac)?outlook(?:-express)?|navermailapp|(?!chrom.+)sparrow|thunderbird|yahoo)(?:m.+ail; |[\/ ])([\w\.]+)/i
], [NAME, VERSION, [TYPE, EMAIL]]
]
});
@@ -238,8 +245,8 @@ const Fetchers = Object.freeze({
],
[NAME, VERSION, [TYPE, FETCHER]],
// Google Bots / Snapchat
[/(feedfetcher-google|google(?:-read-aloud|producer)|(?=bot; )snapchat)/i],
// Google Bots / Cohere / Snapchat / Vercelbot
[/(cohere-ai|vercelbot|feedfetcher-google|google(?:-read-aloud|producer)|(?=bot; )snapchat)/i],
[NAME, [TYPE, FETCHER]],
]
});
@@ -297,8 +304,6 @@ const MediaPlayers = Object.freeze({
], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [
/(htc streaming player)\s[\w_]+\s\/\s([\d\.]+)/i, // HTC Streaming Player
/(java|python-urllib|python-requests|wget|libcurl)\/([\w\.-_]+)/i,
// Java/urllib/requests/wget/cURL
/(lavf)([\d\.]+)/i // Lavf (FFMPEG)
], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [
@@ -374,8 +379,8 @@ const MediaPlayers = Object.freeze({
const Libraries = Object.freeze({
browser : [
// Axios/jsdom/Scrapy
[/\b(axios|jsdom|scrapy)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, LIBRARY]]
// Axios/jsdom/Scrapy/Java/urllib/requests
[/\b(axios|jsdom|scrapy|java|python-urllib|python-requests)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, LIBRARY]]
]
});

View File

@@ -1,13 +1,14 @@
// Type definitions for Helpers submodule of UAParser.js v2.0.0-rc.3
// Type definitions for Helpers submodule of UAParser.js v2.0.0
// Project: https://github.com/faisalman/ua-parser-js
// Definitions by: Faisal Salman <https://github.com/faisalman>
import { IResult } from "../main/ua-parser";
declare function getDeviceVendor(model: string): string | undefined;
declare function isAppleSilicon(res: IResult, useFeatureDetection?: boolean): boolean;
declare function isBot(res: IResult): boolean;
declare function isChromeFamily(res: IResult): boolean;
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;
@@ -16,6 +17,7 @@ declare function isStandalonePWA(): boolean;
export {
getDeviceVendor,
isAppleSilicon,
isAIBot,
isBot,
isChromeFamily,
isElectron,

View File

@@ -1,26 +1,30 @@
///////////////////////////////////////////////
/* Helpers for UAParser.js v2.0.0-rc.3
/* Helpers for UAParser.js v2.0.0
https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com>
UAParser.js PRO Personal License */
UAParser.js PRO Enterprise 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 { isFromEU } = require('detect-europe-js');
const { isFrozenUA } = require('ua-is-frozen');
const { isStandalonePWA } = require('is-standalone-pwa');
const toResult = (value, head, ext) => typeof value === 'string' ? UAParser(value, head, ext) : value;
const getDeviceVendor = (model) => UAParser(`Mozilla/5.0 (Linux; Android 10; ${model}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36`).device.vendor;
const isAppleSilicon = (res, useFeatureDetection) => {
const isAppleSilicon = (resultOrUA) => {
const res = toResult(resultOrUA);
if (res.os.is(OS.MACOS)) {
if (res.cpu.is(CPU.ARM)) {
return true;
}
if (useFeatureDetection) {
if (typeof resultOrUA !== 'string' && typeof window !== 'undefined') {
try {
const canvas = document.createElement('canvas');
const webgl = canvas.getContext('webgl2') || canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
@@ -37,9 +41,85 @@ const isAppleSilicon = (res, useFeatureDetection) => {
return false;
}
const isBot = (res) => ['cli', 'crawler', 'fetcher', 'library'].includes(res.browser.type);
const isAIBot = (resultOrUA) => [
const isChromeFamily = (res) => res.engine.is(Engine.BLINK);
// AI2
'ai2bot',
// Amazon
'amazonbot',
// Anthropic
'anthropic-ai',
'claude-web',
'claudebot',
// Apple
'applebot',
'applebot-extended',
// ByteDance
'bytespider',
// Common Crawl
'ccbot',
// DataForSeo
'dataforseobot',
// Diffbot
'diffbot',
// Google
'googleother',
'googleother-image',
'googleother-video',
'google-extended',
// Hive AI
'imagesiftbot',
// Huawei
'petalbot',
// Meta
'facebookbot',
'meta-externalagent',
// OpenAI
'gptbot',
'oai-searchbot',
// Perplexity
'perplexitybot',
// Timpi
'timpibot',
// Velen.io
'velenpublicwebcrawler',
// Webz.io
'omgili',
'omgilibot',
'webzio-extended',
// You.com
'youbot',
// Zyte
'scrapy'
].includes(String(toResult(resultOrUA, Bots).browser.name).toLowerCase());
const isBot = (resultOrUA) => [
'cli',
'crawler',
'fetcher',
'library'
].includes(toResult(resultOrUA, Bots).browser.type);
const isChromeFamily = (resultOrUA) => toResult(resultOrUA).engine.is(Engine.BLINK);
const isElectron = () => !!(process?.versions?.hasOwnProperty('electron') || // node.js
/ electron\//i.test(navigator?.userAgent)); // browser
@@ -47,6 +127,7 @@ const isElectron = () => !!(process?.versions?.hasOwnProperty('electron') ||
module.exports = {
getDeviceVendor,
isAppleSilicon,
isAIBot,
isBot,
isChromeFamily,
isElectron,

View File

@@ -3,28 +3,32 @@
// Source: /src/helpers/ua-parser-helpers.js
///////////////////////////////////////////////
/* Helpers for UAParser.js v2.0.0-rc.3
/* Helpers for UAParser.js v2.0.0
https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com>
UAParser.js PRO Personal License */
UAParser.js PRO Enterprise 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 { isFromEU } from 'detect-europe-js';
import { isFrozenUA } from 'ua-is-frozen';
import { isStandalonePWA } from 'is-standalone-pwa';
const toResult = (value, head, ext) => typeof value === 'string' ? UAParser(value, head, ext) : value;
const getDeviceVendor = (model) => UAParser(`Mozilla/5.0 (Linux; Android 10; ${model}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36`).device.vendor;
const isAppleSilicon = (res, useFeatureDetection) => {
const isAppleSilicon = (resultOrUA) => {
const res = toResult(resultOrUA);
if (res.os.is(OS.MACOS)) {
if (res.cpu.is(CPU.ARM)) {
return true;
}
if (useFeatureDetection) {
if (typeof resultOrUA !== 'string' && typeof window !== 'undefined') {
try {
const canvas = document.createElement('canvas');
const webgl = canvas.getContext('webgl2') || canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
@@ -41,9 +45,85 @@ const isAppleSilicon = (res, useFeatureDetection) => {
return false;
}
const isBot = (res) => ['cli', 'crawler', 'fetcher', 'library'].includes(res.browser.type);
const isAIBot = (resultOrUA) => [
const isChromeFamily = (res) => res.engine.is(Engine.BLINK);
// AI2
'ai2bot',
// Amazon
'amazonbot',
// Anthropic
'anthropic-ai',
'claude-web',
'claudebot',
// Apple
'applebot',
'applebot-extended',
// ByteDance
'bytespider',
// Common Crawl
'ccbot',
// DataForSeo
'dataforseobot',
// Diffbot
'diffbot',
// Google
'googleother',
'googleother-image',
'googleother-video',
'google-extended',
// Hive AI
'imagesiftbot',
// Huawei
'petalbot',
// Meta
'facebookbot',
'meta-externalagent',
// OpenAI
'gptbot',
'oai-searchbot',
// Perplexity
'perplexitybot',
// Timpi
'timpibot',
// Velen.io
'velenpublicwebcrawler',
// Webz.io
'omgili',
'omgilibot',
'webzio-extended',
// You.com
'youbot',
// Zyte
'scrapy'
].includes(String(toResult(resultOrUA, Bots).browser.name).toLowerCase());
const isBot = (resultOrUA) => [
'cli',
'crawler',
'fetcher',
'library'
].includes(toResult(resultOrUA, Bots).browser.type);
const isChromeFamily = (resultOrUA) => toResult(resultOrUA).engine.is(Engine.BLINK);
const isElectron = () => !!(process?.versions?.hasOwnProperty('electron') || // node.js
/ electron\//i.test(navigator?.userAgent)); // browser
@@ -51,6 +131,7 @@ const isElectron = () => !!(process?.versions?.hasOwnProperty('electron') ||
export {
getDeviceVendor,
isAppleSilicon,
isAIBot,
isBot,
isChromeFamily,
isElectron,

View File

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

View File

@@ -1,7 +1,7 @@
/////////////////////////////////////////////////////////////////////////////////
/* UAParser.js v2.0.0-rc.3
Copyright © 2012-2024 Faisal Salman <f@faisalman.com>
UAParser.js PRO Personal License *//*
/* UAParser.js v2.0.0
Copyright © 2012-2023 Faisal Salman <f@faisalman.com>
UAParser.js PRO Enterprise License *//*
Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.
Supports browser & node.js environment.
Demo : https://uaparser.dev
@@ -19,7 +19,7 @@
// Constants
/////////////
var LIBVERSION = '2.0.0-rc.3',
var LIBVERSION = '2.0.0',
EMPTY = '',
UNKNOWN = '?',
FUNC_TYPE = 'function',
@@ -463,7 +463,7 @@
// Other
/(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|obigo|mosaic|(?:go|ice|up)[\. ]?browser)[-\/ ]?v?([\w\.]+)/i,
// Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Obigo/Mosaic/Go/ICE/UP.Browser
/(links) \(([\w\.]+)/i // Links
/\b(links) \(([\w\.]+)/i // Links
], [NAME, [VERSION, /_/g, '.']], [
/(cobalt)\/([\w\.]+)/i // Cobalt

View File

@@ -3,9 +3,9 @@
// Source: /src/main/ua-parser.js
/////////////////////////////////////////////////////////////////////////////////
/* UAParser.js v2.0.0-rc.3
Copyright © 2012-2024 Faisal Salman <f@faisalman.com>
UAParser.js PRO Personal License *//*
/* UAParser.js v2.0.0
Copyright © 2012-2023 Faisal Salman <f@faisalman.com>
UAParser.js PRO Enterprise License *//*
Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.
Supports browser & node.js environment.
Demo : https://uaparser.dev
@@ -21,7 +21,7 @@
// Constants
/////////////
var LIBVERSION = '2.0.0-rc.3',
var LIBVERSION = '2.0.0',
EMPTY = '',
UNKNOWN = '?',
FUNC_TYPE = 'function',
@@ -465,7 +465,7 @@
// Other
/(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|obigo|mosaic|(?:go|ice|up)[\. ]?browser)[-\/ ]?v?([\w\.]+)/i,
// Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Obigo/Mosaic/Go/ICE/UP.Browser
/(links) \(([\w\.]+)/i // Links
/\b(links) \(([\w\.]+)/i // Links
], [NAME, [VERSION, /_/g, '.']], [
/(cobalt)\/([\w\.]+)/i // Cobalt

View File

@@ -1,6 +1,6 @@
const assert = require('assert');
const { UAParser } = require('../src/main/ua-parser');
const { getDeviceVendor, isAppleSilicon, 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');
describe('getDeviceVendor', () => {
@@ -28,7 +28,23 @@ describe('isAppleSilicon', () => {
const macIntel = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:97.0) Gecko/20100101 Firefox/97.0';
assert.equal(isAppleSilicon(UAParser(macIntel)), false);
assert.equal(isAppleSilicon(macIntel), false);
assert.equal(isAppleSilicon(UAParser(macARM)), true);
assert.equal(isAppleSilicon(macARM), true);
});
});
describe('isAIBot', () => {
it('Can detect AI Bots', () => {
const claudeBot = 'Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)';
const firefox = 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0';
const searchGPT = 'Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; OAI-SearchBot/1.0; +https://openai.com/searchbot';
assert.equal(isAIBot(UAParser(claudeBot, Bots)), true);
assert.equal(isAIBot(claudeBot), true);
assert.equal(isAIBot(firefox), false);
assert.equal(isAIBot(searchGPT), true);
});
});
@@ -46,6 +62,11 @@ describe('isBot', () => {
assert.equal(isBot(botParser.setUA(ahrefsBot).getResult()), true);
assert.equal(isBot(botParser.setUA(scrapy).getResult()), true);
assert.equal(isBot(botParser.setUA(thunderbird).getResult()), false);
assert.equal(isBot(ahrefsBot), true);
assert.equal(isBot(firefox), false);
assert.equal(isBot(scrapy), true);
assert.equal(isBot(thunderbird), false);
});
});
@@ -57,5 +78,7 @@ describe('isChromeFamily', () => {
assert.equal(isChromeFamily(UAParser(edge)), true);
assert.equal(isChromeFamily(UAParser(firefox)), false);
assert.equal(isChromeFamily(edge), true);
assert.equal(isChromeFamily(firefox), false);
});
});

View File

@@ -9,6 +9,36 @@
"type" : "cli"
}
},
{
"desc" : "ELinks",
"ua" : "ELinks/0.11.4-3-lite (textmode; Debian; Linux 2.6.26-1-686 i686;",
"expect" :
{
"name" : "ELinks",
"version" : "0.11.4-3-lite",
"type" : "cli"
}
},
{
"desc" : "ELinks",
"ua" : "ELinks (0.11.3; Linux 2.6.23-hardened-r4 i686; 166x55)",
"expect" :
{
"name" : "ELinks",
"version" : "0.11.3",
"type" : "cli"
}
},
{
"desc" : "HTTPie",
"ua" : "HTTPie/0.9.9",
"expect" :
{
"name" : "HTTPie",
"version" : "0.9.9",
"type" : "cli"
}
},
{
"desc" : "lynx",
"ua" : "Lynx 2.8.8dev.3",

View File

@@ -49,6 +49,26 @@
"type" : "crawler"
}
},
{
"desc" : "AI2Bot",
"ua" : "Mozilla/5.0 (compatible) AI2Bot (+https://www.allenai.org/crawler)",
"expect" :
{
"name" : "AI2Bot",
"version" : "undefined",
"type" : "crawler"
}
},
{
"desc" : "aiHitBot",
"ua" : "Mozilla/5.0 (compatible; aiHitBot/2.9; +https://www.aihitdata.com/about)",
"expect" :
{
"name" : "aiHitBot",
"version" : "2.9",
"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)",
@@ -131,7 +151,7 @@
},
{
"desc" : "DataForSEO",
"ua" : "Mozilla/5.0 (compatible; DataForSeoBot; +https://dataforseo.com/dataforseo-bot) ",
"ua" : "Mozilla/5.0 (compatible; DataForSeoBot; +https://dataforseo.com/dataforseo-bot)",
"expect" :
{
"name" : "DataForSeoBot",
@@ -139,6 +159,16 @@
"type" : "crawler"
}
},
{
"desc" : "Diffbot",
"ua" : "Diffbot/0.1",
"expect" :
{
"name" : "Diffbot",
"version" : "0.1",
"type" : "crawler"
}
},
{
"desc" : "Dotbot",
"ua" : "Mozilla/5.0 (compatible; DotBot/1.2; +https://opensiteexplorer.org/dotbot; help@moz.com)",
@@ -329,6 +359,26 @@
"type" : "crawler"
}
},
{
"desc" : "ImagesiftBot",
"ua" : "Mozilla/5.0 (compatible; ImagesiftBot; +imagesift.com)",
"expect" :
{
"name" : "ImagesiftBot",
"version" : "undefined",
"type" : "crawler"
}
},
{
"desc" : "magpie-crawler",
"ua" : "magpie-crawler/1.1 (robots-txt-checker; +http://www.brandwatch.net)",
"expect" :
{
"name" : "magpie-crawler",
"version" : "1.1",
"type" : "crawler"
}
},
{
"desc" : "Meta-ExternalAgent",
"ua" : "meta-externalagent/1.1 (+https://developers.facebook.com/docs/sharing/webmasters/crawler)",
@@ -360,6 +410,26 @@
"type" : "crawler"
}
},
{
"desc" : "Omgili",
"ua" : "omgili/0.5 +https://omgili.com",
"expect" :
{
"name" : "omgili",
"version" : "0.5",
"type" : "crawler"
}
},
{
"desc" : "Omgilibot",
"ua" : "omgilibot/0.3 +http://www.omgili.com/Crawler.html",
"expect" :
{
"name" : "omgilibot",
"version" : "0.3",
"type" : "crawler"
}
},
{
"desc" : "OpenAI Search",
"ua" : "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; OAI-SearchBot/1.0; +https://openai.com/searchbot",
@@ -410,6 +480,36 @@
"type" : "crawler"
}
},
{
"desc" : "SeznamBot",
"ua" : "Mozilla/5.0 (compatible; SeznamBot/4.0-RC1; +http://napoveda.seznam.cz/seznambot-intro/)",
"expect" :
{
"name" : "SeznamBot",
"version" : "4.0-RC1",
"type" : "crawler"
}
},
{
"desc" : "Teoma",
"ua" : "Mozilla/2.0 (compatible; Ask Jeeves/Teoma; +http://sp.ask.com/docs/about/tech_crawling.html)",
"expect" :
{
"name" : "Teoma",
"version" : "undefined",
"type" : "crawler"
}
},
{
"desc" : "Timpibot",
"ua" : "Timpibot/0.8 (+http://www.timpi.io)",
"expect" :
{
"name" : "Timpibot",
"version" : "0.8",
"type" : "crawler"
}
},
{
"desc" : "TurnitinBot",
"ua" : "TurnitinBot (https://turnitin.com/robot/crawlerinfo.html)",
@@ -420,6 +520,16 @@
"type" : "crawler"
}
},
{
"desc" : "VelenPublicWebCrawler",
"ua" : "Mozilla/5.0 (compatible; VelenPublicWebCrawler/1.0; +https://velen.io)",
"expect" :
{
"name" : "VelenPublicWebCrawler",
"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)",
@@ -469,5 +579,15 @@
"version" : "undefined",
"type" : "crawler"
}
},
{
"desc" : "YouBot",
"ua" : "YouBot (+http://www.you.com)",
"expect" :
{
"name" : "YouBot",
"version" : "undefined",
"type" : "crawler"
}
}
]

View File

@@ -1,4 +1,34 @@
[
{
"desc" : "Airmail",
"ua" : "Airmail 1.0 rv:148 (Macintosh; Mac OS X 10.8.3; en_BE)",
"expect" :
{
"name" : "Airmail",
"version" : "1.0",
"type" : "email"
}
},
{
"desc" : "BlueMail",
"ua" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) BlueMail/0.10.31 Chrome/61.0.3163.100 Electron/2.0.18 Safari/537.36",
"expect" :
{
"name" : "BlueMail",
"version" : "0.10.31",
"type" : "email"
}
},
{
"desc" : "BlueMail",
"ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/16A405 BlueMail iOS",
"expect" :
{
"name" : "BlueMail",
"version" : "iOS",
"type" : "email"
}
},
{
"desc" : "Evolution",
"ua" : "Evolution/3.52.3",
@@ -9,6 +39,26 @@
"type" : "email"
}
},
{
"desc" : "eM Client",
"ua" : "eMClient/9.2.2157.0",
"expect" :
{
"name" : "eMClient",
"version" : "9.2.2157.0",
"type" : "email"
}
},
{
"desc" : "Foxmail",
"ua" : "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36 foxmail/7.2.15.80",
"expect" :
{
"name" : "foxmail",
"version" : "7.2.15.80",
"type" : "email"
}
},
{
"desc" : "KMail",
"ua" : "KMail/4.14.10 (FreeBSD/12.0-CURRENT; KDE/4.14.10; amd64; ; )",
@@ -59,6 +109,26 @@
"type" : "email"
}
},
{
"desc" : "NaverMailApp",
"ua" : "NaverMailApp/2.1.23 (Android 10; SM-N960N)",
"expect" :
{
"name" : "NaverMailApp",
"version" : "2.1.23",
"type" : "email"
}
},
{
"desc" : "Sparrow",
"ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/604.5.6 (KHTML, like Gecko) Sparrow/1043.1",
"expect" :
{
"name" : "Sparrow",
"version" : "1043.1",
"type" : "email"
}
},
{
"desc" : "Thunderbird",
"ua" : "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0",
@@ -68,5 +138,25 @@
"version" : "78.13.0",
"type" : "email"
}
},
{
"desc" : "Yahoo! Mail",
"ua" : "YahooMobile/1.0 (mail; 3.0.5.1311380); (Linux; U; Android 4.0.3; htc_runnymede Build/ICE_CREAM_SANDWICH_MR1);",
"expect" :
{
"name" : "Yahoo",
"version" : "3.0.5.1311380",
"type" : "email"
}
},
{
"desc" : "Yahoo! Mail",
"ua" : "YahooMobileMail/1.0 (Android Mail; 1.3.10) (supersonic;HTC;PC36100;2.3.5/GRJ90) ",
"expect" :
{
"name" : "Yahoo",
"version" : "1.3.10",
"type" : "email"
}
}
]

View File

@@ -118,5 +118,15 @@
"version" : "2.0",
"type" : "fetcher"
}
},
{
"desc" : "Vercelbot",
"ua" : "Vercelbot (+https://vercel.com)",
"expect" :
{
"name" : "Vercelbot",
"version" : "undefined",
"type" : "fetcher"
}
}
]

View File

@@ -1,4 +1,54 @@
[
{
"desc" : "Axios",
"ua" : "axios/1.7.2",
"expect" :
{
"name" : "axios",
"version" : "1.7.2",
"type" : "library"
}
},
{
"desc" : "Java",
"ua" : "Java/1.6.0_14",
"expect" :
{
"name" : "Java",
"version" : "1.6.0_14",
"type" : "library"
}
},
{
"desc" : "jsdom",
"ua" : "Mozilla/5.0 (unknown OS) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/11.12.0",
"expect" :
{
"name" : "jsdom",
"version" : "11.12.0",
"type" : "library"
}
},
{
"desc" : "Python urllib",
"ua" : "Python-urllib/2.6",
"expect" :
{
"name" : "Python-urllib",
"version" : "2.6",
"type" : "library"
}
},
{
"desc" : "Python requests",
"ua" : "python-requests/2.32",
"expect" :
{
"name" : "python-requests",
"version" : "2.32",
"type" : "library"
}
},
{
"desc" : "Scrapy",
"ua" : "Scrapy/1.5.0 (+https://scrapy.org)",