Update version to 2.0.0-rc.1

This commit is contained in:
Faisal Salman 2024-10-29 22:29:51 +07:00
parent aad163ffc5
commit 1e0175c001
14 changed files with 256 additions and 192 deletions

View File

@ -1,5 +1,25 @@
# UAParser.js Changelog # UAParser.js Changelog
## Version 2.0.0-rc.1
- Fix Python Request mistakenly identified as Meta Quest
- Add new browser: Helio
- Add new device: itel, Nothing, Pico, TCL
- Add new engine: ArkWeb
- Add new OS: OpenHarmony, Pico
- Improve browser detection: Quark
- Improve device detection: Xiaomi, Amazon Echo Show, Google Chromecast, Samsung Galaxy Watch
- `ua-parser-js/helpers` submodule:
- Add new method:
- `getDeviceVendor()` to guess for a device vendor based on its model name
- `isElectron()` to check if current window is running inside Electron
- `isFromEU()` to check if current window is from an EU (European Union) country
- `isStandalonePWA()` to check if current window is a standalone PWA
- Rename `isChromiumBased()` to `isChromeFamily()`
- Update `isAppleSilicon()` to also checks for WebGL renderer info
- `ua-parser-js/extensions` submodule:
- Restore `bots` as a compilation of all these browser types: `clis`, `crawlers`, `fetchers`, and `modules`
## Version 2.0.0-beta.3 ## Version 2.0.0-beta.3
- Breaking: - Breaking:

View File

@ -19,81 +19,14 @@ The most comprehensive, compact, & up-to-date isomorphic JavaScript library to d
user's Browser, Engine, OS, CPU, and Device type/model. Runs either in browser user's Browser, Engine, OS, CPU, and Device type/model. Runs either in browser
(client-side) or node.js (server-side). (client-side) or node.js (server-side).
# Overview # Demo
```js
import { UAParser } from 'ua-parser-js';
// 1. Problem:
// Imagine getting this wild user-agent string from a visitor:
const ua = `Mozilla/5.0 (Linux; Android 10; STK-LX1
Build/HONORSTK-LX1; wv) AppleWebKit/537.36 (KHTML,
like Gecko) Version/4.0 Chrome/110.0.5481.153 Mobile
Safari/537.36 musical_ly_2022803040 JsSdk/1.0
NetType/WIFI Channel/huaweiadsglobal_int
AppName/musical_ly app_version/28.3.4 ByteLocale/en
ByteFullLocale/en Region/IQ Spark/1.2.7-alpha.8
AppVersion/28.3.4 PIA/1.5.11 BytedanceWebview/d8a21c6`;
// Note: this is a real user-agent (what???)
// 2. Solution:
// Just pass the complex user-agent string to `UAParser`
const parser = new UAParser(ua);
// 3. Result:
// And voila!
console.log(parser.getBrowser());
// { name : "TikTok", version : "28.3.4", major : "28", type: undefined }
console.log(parser.getCPU());
// { architecture : undefined }
console.log(parser.getEngine());
// { name : "Blink", version : "110.0.5481.153" }
console.log(parser.getDevice());
// { type : "mobile", vendor : "Huawei", model : "STK-LX1" }
console.log(parser.getOS());
// { name : "Android", version : "10" }
console.log(parser.getResult());
/*
{
ua: "Mozilla/5.0 (Linux; Android 10; STK-LX1 Build/HONORSTK-LX1; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/110.0.5481.153 Mobile Safari/537.36 musical_ly_2022803040 JsSdk/1.0 NetType/WIFI Channel/huaweiadsglobal_int AppName/musical_ly app_version/28.3.4 ByteLocale/en ByteFullLocale/en Region/IQ Spark/1.2.7-alpha.8 AppVersion/28.3.4 PIA/1.5.11 BytedanceWebview/d8a21c6",
browser: {
name: "TikTok",
version: "28.3.4",
major: "28"
},
cpu: {},
device: {
type: "mobile",
model: "STK-LX1",
vendor: "Huawei"
},
engine: {
name: "Blink",
version: "110.0.5481.153"
},
os: {
name: "Android",
version: "10"
}
}
*/
// 4. Conclusion:
// The visitor is browsing from a TikTok app using an Android-powered Huawei device
// Phew! Thanks, UAParser.js!
```
* Live demo: https://uaparser.dev * Live demo: https://uaparser.dev
# Documentation # Documentation
* v1.0: https://github.com/faisalman/ua-parser-js/tree/1.0.38#documentation * `version 1.x` : https://github.com/faisalman/ua-parser-js/tree/1.0.x#documentation
* v2.0: https://docs.uaparser.dev * `version 2.x` : https://docs.uaparser.dev
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.
@ -234,7 +167,7 @@ see what's new & breaking.
<td></td> <td></td>
<td></td> <td></td>
<td></td> <td></td>
<td><strong title="1 project per 1 license"></strong></td> <td><strong title="1 project per 1 license"></strong></td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
@ -257,9 +190,9 @@ see what's new & breaking.
<td>Price</td> <td>Price</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 (<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/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="$12 (one-time fee)">$12 (<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="$25 (one-time fee)">$25 (<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="$500 (one-time fee)">$500 (<a target="_blank" href="https://raw.githubusercontent.com/faisalman/ua-parser-js/pro-enterprise/LICENSE.md">License</a>)</strong></td> <td><strong title="$588 (one-time fee)">$588 (<a target="_blank" href="https://raw.githubusercontent.com/faisalman/ua-parser-js/pro-enterprise/LICENSE.md">License</a>)</strong></td>
</tr> </tr>
</tbody> </tbody>
<tfoot> <tfoot>
@ -287,3 +220,5 @@ Made with [contributors-img](https://contrib.rocks).
<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/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> <a href="https://opencollective.com/ua-parser-js"><img src="https://opencollective.com/ua-parser-js/individuals.svg?avatarHeight=64"></a>
Support the open-source versions of UAParser.js on [OpenCollective](https://opencollective.com/ua-parser-js) or [GitHub Sponsors](https://github.com/sponsors/faisalman).

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "ua-parser-js", "name": "ua-parser-js",
"version": "2.0.0-beta.3", "version": "2.0.0-rc.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "ua-parser-js", "name": "ua-parser-js",
"version": "2.0.0-beta.3", "version": "2.0.0-rc.1",
"funding": [ "funding": [
{ {
"type": "opencollective", "type": "opencollective",

View File

@ -1,7 +1,7 @@
{ {
"title": "UAParser.js", "title": "UAParser.js",
"name": "ua-parser-js", "name": "ua-parser-js",
"version": "2.0.0-beta.3", "version": "2.0.0-rc.1",
"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

@ -1,5 +1,5 @@
/////////////////////////////////////////////// ///////////////////////////////////////////////
/* Enums for UAParser.js v2.0.0-beta.3 /* Enums for UAParser.js v2.0.0-rc.1
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 */

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.0-beta.3 /* Enums for UAParser.js v2.0.0-rc.1
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,8 +12,8 @@
/*jshint esversion: 6 */ /*jshint esversion: 6 */
const Browser = Object.freeze({ const Browser = Object.freeze({
_2345_EXPLORER: '2345Explorer', '2345_EXPLORER': '2345Explorer',
_360: '360 Browser', '360': '360 Browser',
ALIPAY: 'Alipay', ALIPAY: 'Alipay',
AMAYA: 'Amaya', AMAYA: 'Amaya',
ANDROID: 'Android Browser', ANDROID: 'Android Browser',
@ -56,6 +56,7 @@ const Browser = Object.freeze({
FLOW: 'Flow', FLOW: 'Flow',
GO: 'GoBrowser', GO: 'GoBrowser',
GOOGLE_SEARCH: 'GSA', GOOGLE_SEARCH: 'GSA',
HELIO: 'Helio',
HEYTAP: 'HeyTap', HEYTAP: 'HeyTap',
HUAWEI: 'Huawei Browser', HUAWEI: 'Huawei Browser',
ICAB: 'iCab', ICAB: 'iCab',
@ -161,6 +162,7 @@ const BrowserType = Object.freeze({
}); });
const CPU = Object.freeze({ const CPU = Object.freeze({
'68K': '68k',
ARM : 'arm', ARM : 'arm',
ARM_64: 'arm64', ARM_64: 'arm64',
ARM_HF: 'armhf', ARM_HF: 'armhf',
@ -171,7 +173,6 @@ const CPU = Object.freeze({
IRIX_64: 'irix64', IRIX_64: 'irix64',
MIPS: 'mips', MIPS: 'mips',
MIPS_64: 'mips64', MIPS_64: 'mips64',
M68K: '68k',
PA_RISC: 'pa-risc', PA_RISC: 'pa-risc',
PPC: 'ppc', PPC: 'ppc',
SPARC: 'sparc', SPARC: 'sparc',
@ -212,6 +213,7 @@ const Vendor = Object.freeze({
HTC: 'HTC', HTC: 'HTC',
HUAWEI: 'Huawei', HUAWEI: 'Huawei',
INFINIX: 'Infinix', INFINIX: 'Infinix',
ITEL: 'itel',
JOLLA: 'Jolla', JOLLA: 'Jolla',
KOBO: 'Kobo', KOBO: 'Kobo',
LENOVO: 'Lenovo', LENOVO: 'Lenovo',
@ -222,6 +224,7 @@ const Vendor = Object.freeze({
NEXIAN: 'Nexian', NEXIAN: 'Nexian',
NINTENDO: 'Nintendo', NINTENDO: 'Nintendo',
NOKIA: 'Nokia', NOKIA: 'Nokia',
NOTHING: 'Nothing',
NVIDIA: 'Nvidia', NVIDIA: 'Nvidia',
ONEPLUS: 'OnePlus', ONEPLUS: 'OnePlus',
OPPO: 'OPPO', OPPO: 'OPPO',
@ -239,6 +242,7 @@ const Vendor = Object.freeze({
SIEMENS: 'Siemens', SIEMENS: 'Siemens',
SONY: 'Sony', SONY: 'Sony',
SPRINT: 'Sprint', SPRINT: 'Sprint',
TCL: 'TCL',
TECHNISAT: 'TechniSAT', TECHNISAT: 'TechniSAT',
TECNO: 'Tecno', TECNO: 'Tecno',
TESLA: 'Tesla', TESLA: 'Tesla',
@ -255,6 +259,7 @@ const Vendor = Object.freeze({
const Engine = Object.freeze({ const Engine = Object.freeze({
AMAYA: 'Amaya', AMAYA: 'Amaya',
ARKWEB: 'ArkWeb',
BLINK: 'Blink', BLINK: 'Blink',
EDGEHTML: 'EdgeHTML', EDGEHTML: 'EdgeHTML',
FLOW: 'Flow', FLOW: 'Flow',
@ -321,6 +326,7 @@ const OS = Object.freeze({
NETRANGE: 'NetRange', NETRANGE: 'NetRange',
NETTV: 'NetTV', NETTV: 'NetTV',
NINTENDO: 'Nintendo', NINTENDO: 'Nintendo',
OPENHARMONY: 'OpenHarmony',
OPENBSD: 'OpenBSD', OPENBSD: 'OpenBSD',
OPENVMS: 'OpenVMS', OPENVMS: 'OpenVMS',
OS2: 'OS/2', OS2: 'OS/2',
@ -347,7 +353,6 @@ const OS = Object.freeze({
UBUNTU: 'Ubuntu', UBUNTU: 'Ubuntu',
UNIX: 'Unix', UNIX: 'Unix',
VECTORLINUX: 'VectorLinux', VECTORLINUX: 'VectorLinux',
VIERA: 'Viera',
WATCHOS: 'watchOS', WATCHOS: 'watchOS',
WEBOS: 'WebOS', WEBOS: 'WebOS',
WINDOWS: 'Windows', WINDOWS: 'Windows',

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////// ///////////////////////////////////////////////
/* Extensions for UAParser.js v2.0.0-beta.3 /* Extensions for UAParser.js v2.0.0-rc.1
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 */

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.0-beta.3 /* Extensions for UAParser.js v2.0.0-rc.1
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 */
@ -23,6 +23,7 @@ const CLI = 'cli';
const EMAIL = 'email'; const EMAIL = 'email';
const FETCHER = 'fetcher'; const FETCHER = 'fetcher';
const INAPP = 'inapp'; const INAPP = 'inapp';
const MEDIAPLAYER = 'mediaplayer';
const MODULE = 'module'; const MODULE = 'module';
////////////////////// //////////////////////
@ -42,45 +43,48 @@ const CLIs = Object.freeze({
const Crawlers = Object.freeze({ const Crawlers = Object.freeze({
browser : [ browser : [
[
// AhrefsBot - https://ahrefs.com/robot
// Amazonbot - https://developer.amazon.com/amazonbot // Amazonbot - https://developer.amazon.com/amazonbot
// Applebot - http://apple.com/go/applebot // Applebot - http://apple.com/go/applebot
// Bingbot - http://www.bing.com/bingbot.htm // Bingbot - http://www.bing.com/bingbot.htm
// 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
// MJ12bot - https://mj12bot.com/ // MJ12bot - https://mj12bot.com/
// OpenAI Search - https://platform.openai.com/docs/bots
// SemrushBot - http://www.semrush.com/bot.html // SemrushBot - http://www.semrush.com/bot.html
[/((?:amazon|apple|bing|duckduck|facebook|gpt|mj12|semrush)bot)\/([\w\.]+)/i], /((?:ahrefs|amazon|apple|bing|dot|duckduck|facebook|gpt|mj12|oai-search|semrush)bot)\/([\w\.]+)/i,
[NAME, VERSION, [TYPE, CRAWLER]],
// Baiduspider https://help.baidu.com/question?prod_id=99&class=0&id=3001 // Baiduspider https://help.baidu.com/question?prod_id=99&class=0&id=3001
[/(baiduspider)[-imagevdonsfcpr]{0,6}\/([\w\.]+)/i], /(baiduspider)[-imagevdonsfcpr]{0,6}\/([\w\.]+)/i,
// ClaudeBot
/(claude(?:bot|-web))\/([\w\.]+)/i,
// Coc Coc Bot - https://help.coccoc.com/en/search-engine
/(coccocbot-(?:image|web))\/([\w\.]+)/i,
// Googlebot - http://www.google.com/bot.html
/(google(?:bot|other)(?:-image|-video|-news|-extended)?|(?:storebot-)?google(?:-inspectiontool)?)\/?([\w\.]*)/i,
// Sogou Spider
/(sogou (?:pic|head|web|orion|news) spider)\/([\w\.]+)/i,
// Yahoo! Japan - https://support.yahoo-net.jp/PccSearch/s/article/H000007955
/(y!?j-(?:asr|br[uw]|dscv|mmp|vsidx|wsc))\/([\w\.]+)/i,
// Yandex Bots - https://yandex.com/bots
/(yandex(?:(?:mobile)?(?:accessibility|additional|renderresources|screenshot|sprav)?bot|image(?:s|resizer)|video(?:parser)?|blogs|adnet|favicons|fordomain|market|media|metrika|news|ontodb(?:api)?|pagechecker|partner|rca|tracker|turbo|vertis|webmaster|antivirus))\/([\w\.]+)/i
],
[NAME, VERSION, [TYPE, CRAWLER]], [NAME, VERSION, [TYPE, CRAWLER]],
// Bytespider // Bytespider
// Yahoo! Slurp - http://help.yahoo.com/help/us/ysearch/slurp // Yahoo! Slurp - http://help.yahoo.com/help/us/ysearch/slurp
[/((?:bytespider|(?=yahoo! )slurp))/i], [/((?:bytespider|(?=yahoo! )slurp))/i],
[NAME, [TYPE, CRAWLER]], [NAME, [TYPE, CRAWLER]]
// ClaudeBot
[/(claude(?:bot|-web))\/([\w\.]+)/i],
[NAME, VERSION, [TYPE, CRAWLER]],
// Googlebot - http://www.google.com/bot.html
[
/(google(?:bot|other)(?:-image|-video|-news|-extended)?|(?:storebot-)?google(?:-inspectiontool)?)\/?([\w\.]*)/i
],
[NAME, VERSION, [TYPE, CRAWLER]],
// Sogou Spider
[/(sogou (?:pic|head|web|orion|news) spider)\/([\w\.]+)/i],
[NAME, VERSION, [TYPE, CRAWLER]],
// Yandex Bots - https://yandex.com/bots
[
/(yandex(?:(?:mobile)?(?:accessibility|additional|renderresources|screenshot|sprav)?bot|image(?:s|resizer)|video(?:parser)?|blogs|adnet|favicons|fordomain|market|media|metrika|news|ontodb(?:api)?|pagechecker|partner|rca|tracker|turbo|vertis|webmaster|antivirus))\/([\w\.]+)/i
],
[NAME, VERSION, [TYPE, CRAWLER]]
] ]
}); });
@ -181,29 +185,30 @@ const Emails = Object.freeze({
const Fetchers = Object.freeze({ const Fetchers = Object.freeze({
browser : [ browser : [
// BingPreview / Mastodon / Pinterestbot / Redditbot / Telegrambot / Twitterbot [
[/(bingpreview|mastodon|(?:discord|linkedin|pinterest|reddit|telegram|twitter)bot)\/([\w\.]+)/i], // AhrefsSiteAudit - https://ahrefs.com/robot/site-audit
// ChatGPT-User - https://platform.openai.com/docs/plugins/bot
// BingPreview / Mastodon / Pinterestbot / Redditbot / Rogerbot / Telegrambot / Twitterbot / UptimeRobot
/(ahrefssiteaudit|bingpreview|chatgpt-user|mastodon|(?:discord|linkedin|pinterest|reddit|roger|telegram|twitter|uptimero)bot)\/([\w\.]+)/i,
// Slackbot - https://api.slack.com/robots
/(slack(?:bot)?(?:-imgproxy|-linkexpanding)?) ([\w\.]+)/i,
// WhatsApp
/(whatsapp)\/([\w\.]+)[\/ ][ianw]/i,
// Yahoo! Japan
/(y!?j-dlc)\/([\w\.]+)/i,
// Yandex Bots - https://yandex.com/bots
/(yandex(?:calendar|direct(?:dyn)?|searchshop)|yadirectfetcher)\/([\w\.]+)/i,
/(yandex(?:sitelinks|userproxy))/i
],
[NAME, VERSION, [TYPE, FETCHER]], [NAME, VERSION, [TYPE, FETCHER]],
// Google Bots / Snapchat // Google Bots / Snapchat
[/(feedfetcher-google|google-read-aloud|(?=bot; )snapchat)/i], [/(feedfetcher-google|google-read-aloud|(?=bot; )snapchat)/i],
[NAME, [TYPE, FETCHER]], [NAME, [TYPE, FETCHER]],
// Slackbot - https://api.slack.com/robots
[/(slack(?:bot)?(?:-imgproxy|-linkexpanding)?) ([\w\.]+)/i],
[NAME, VERSION, [TYPE, FETCHER]],
// WhatsApp
[/(whatsapp)\/([\w\.]+)[\/ ][ianw]/i],
[NAME, VERSION, [TYPE, FETCHER]],
// Yandex Bots - https://yandex.com/bots
[
/(yandex(?:calendar|direct(?:dyn)?|searchshop)|yadirectfetcher)\/([\w\.]+)/i,
/(yandex(?:sitelinks|userproxy))/i
],
[NAME, VERSION, [TYPE, FETCHER]]
] ]
}); });
@ -213,7 +218,11 @@ const Fetchers = Object.freeze({
const InApps = Object.freeze({ const InApps = Object.freeze({
browser : [ browser : [
[/chatlyio\/([\d\.]+)/i], [VERSION, 'Slack', [TYPE, INAPP]] // Slack
[/chatlyio\/([\d\.]+)/i], [VERSION, 'Slack', [TYPE, INAPP]],
// Yahoo! Japan
[/jp\.co\.yahoo\.android\.yjtop\/([\d\.]+)/i], [VERSION, 'Yahoo! Japan', [TYPE, INAPP]]
] ]
}); });
@ -226,13 +235,13 @@ const MediaPlayers = Object.freeze({
/(apple(?:coremedia|))\/([\w\._]+)/i, // Generic Apple CoreMedia /(apple(?:coremedia|))\/([\w\._]+)/i, // Generic Apple CoreMedia
/(coremedia) v([\w\._]+)/i /(coremedia) v([\w\._]+)/i
], [NAME, VERSION], [ ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [
/(aqualung|lyssna|bsplayer)\/([\w\.-]+)/i // Aqualung/Lyssna/BSPlayer /(aqualung|lyssna|bsplayer)\/([\w\.-]+)/i // Aqualung/Lyssna/BSPlayer
], [NAME, VERSION], [ ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [
/(ares|ossproxy)\s([\w\.-]+)/i // Ares/OSSProxy /(ares|ossproxy)\s([\w\.-]+)/i // Ares/OSSProxy
], [NAME, VERSION], [ ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [
/(audacious|audimusicstream|amarok|bass|core|dalvik|gnomemplayer|music on console|nsplayer|psp-internetradioplayer|videos)\/([\w\.-]+)/i, /(audacious|audimusicstream|amarok|bass|core|dalvik|gnomemplayer|music on console|nsplayer|psp-internetradioplayer|videos)\/([\w\.-]+)/i,
// Audacious/AudiMusicStream/Amarok/BASS/OpenCORE/Dalvik/GnomeMplayer/MoC // Audacious/AudiMusicStream/Amarok/BASS/OpenCORE/Dalvik/GnomeMplayer/MoC
@ -240,90 +249,90 @@ const MediaPlayers = Object.freeze({
/(clementine|music player daemon)\s([\w\.-]+)/i, // Clementine/MPD /(clementine|music player daemon)\s([\w\.-]+)/i, // Clementine/MPD
/(lg player|nexplayer)\s([\d\.]+)/i, /(lg player|nexplayer)\s([\d\.]+)/i,
/player\/(nexplayer|lg player)\s([\w\.-]+)/i // NexPlayer/LG Player /player\/(nexplayer|lg player)\s([\w\.-]+)/i // NexPlayer/LG Player
], [NAME, VERSION], [ ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [
/(nexplayer)\s([\w\.-]+)/i // Nexplayer /(nexplayer)\s([\w\.-]+)/i // Nexplayer
], [NAME, VERSION], [ ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [
/(flrp)\/([\w\.-]+)/i // Flip Player /(flrp)\/([\w\.-]+)/i // Flip Player
], [[NAME, 'Flip Player'], VERSION], [ ], [[NAME, 'Flip Player'], VERSION, [TYPE, MEDIAPLAYER]], [
/(fstream|nativehost|queryseekspider|ia-archiver|facebookexternalhit)/i /(fstream|nativehost|queryseekspider|ia-archiver|facebookexternalhit)/i
// FStream/NativeHost/QuerySeekSpider/IA Archiver/facebookexternalhit // FStream/NativeHost/QuerySeekSpider/IA Archiver/facebookexternalhit
], [NAME], [ ], [NAME, [TYPE, MEDIAPLAYER]], [
/(gstreamer) souphttpsrc.+libsoup\/([\w\.-]+)/i /(gstreamer) souphttpsrc.+libsoup\/([\w\.-]+)/i
// Gstreamer // Gstreamer
], [NAME, VERSION], [ ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [
/(htc streaming player)\s[\w_]+\s\/\s([\d\.]+)/i, // HTC Streaming Player /(htc streaming player)\s[\w_]+\s\/\s([\d\.]+)/i, // HTC Streaming Player
/(java|python-urllib|python-requests|wget|libcurl)\/([\w\.-_]+)/i, /(java|python-urllib|python-requests|wget|libcurl)\/([\w\.-_]+)/i,
// Java/urllib/requests/wget/cURL // Java/urllib/requests/wget/cURL
/(lavf)([\d\.]+)/i // Lavf (FFMPEG) /(lavf)([\d\.]+)/i // Lavf (FFMPEG)
], [NAME, VERSION], [ ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [
/(htc_one_s)\/([\d\.]+)/i, // HTC One S /(htc_one_s)\/([\d\.]+)/i, // HTC One S
], [[NAME, /_/g, ' '], VERSION], [ ], [[NAME, /_/g, ' '], VERSION, [TYPE, MEDIAPLAYER]], [
/(mplayer)(?:\s|\/)(?:(?:sherpya-){0,1}svn)(?:-|\s)(r\d+(?:-\d+[\w\.-]+))/i, /(mplayer)(?:\s|\/)(?:(?:sherpya-){0,1}svn)(?:-|\s)(r\d+(?:-\d+[\w\.-]+))/i,
// MPlayer SVN // MPlayer SVN
], [NAME, VERSION], [ ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [
/(mplayer)(?:\s|\/)([\w\.-]+)/i, // MPlayer /(mplayer)(?:\s|\/)([\w\.-]+)/i, // MPlayer
/(mplayer) unknown-([\w\.\-]+)/i // MPlayer UNKNOWN /(mplayer) unknown-([\w\.\-]+)/i // MPlayer UNKNOWN
], [NAME, VERSION], [ ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [
/(mplayer)/i, // MPlayer (no other info) /(mplayer)/i, // MPlayer (no other info)
/(yourmuze)/i, // YourMuze /(yourmuze)/i, // YourMuze
/(media player classic|nero showtime)/i // Media Player Classic/Nero ShowTime /(media player classic|nero showtime)/i // Media Player Classic/Nero ShowTime
], [NAME], [ ], [NAME, [TYPE, MEDIAPLAYER]], [
/(nero (?:home|scout))\/([\w\.-]+)/i // Nero Home/Nero Scout /(nero (?:home|scout))\/([\w\.-]+)/i // Nero Home/Nero Scout
], [NAME, VERSION], [ ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [
/(nokia\d+)\/([\w\.-]+)/i // Nokia /(nokia\d+)\/([\w\.-]+)/i // Nokia
], [NAME, VERSION], [ ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [
/\s(songbird)\/([\w\.-]+)/i // Songbird/Philips-Songbird /\s(songbird)\/([\w\.-]+)/i // Songbird/Philips-Songbird
], [NAME, VERSION], [ ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [
/(winamp)3 version ([\w\.-]+)/i, // Winamp /(winamp)3 version ([\w\.-]+)/i, // Winamp
/(winamp)\s([\w\.-]+)/i, /(winamp)\s([\w\.-]+)/i,
/(winamp)mpeg\/([\w\.-]+)/i /(winamp)mpeg\/([\w\.-]+)/i
], [NAME, VERSION], [ ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [
/(ocms-bot|tapinradio|tunein radio|unknown|winamp|inlight radio)/i // OCMS-bot/tap in radio/tunein/unknown/winamp (no other info) /(ocms-bot|tapinradio|tunein radio|unknown|winamp|inlight radio)/i // OCMS-bot/tap in radio/tunein/unknown/winamp (no other info)
// inlight radio // inlight radio
], [NAME], [ ], [NAME, [TYPE, MEDIAPLAYER]], [
/(quicktime|rma|radioapp|radioclientapplication|soundtap|totem|stagefright|streamium)\/([\w\.-]+)/i /(quicktime|rma|radioapp|radioclientapplication|soundtap|totem|stagefright|streamium)\/([\w\.-]+)/i
// QuickTime/RealMedia/RadioApp/RadioClientApplication/ // QuickTime/RealMedia/RadioApp/RadioClientApplication/
// SoundTap/Totem/Stagefright/Streamium // SoundTap/Totem/Stagefright/Streamium
], [NAME, VERSION], [ ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [
/(smp)([\d\.]+)/i // SMP /(smp)([\d\.]+)/i // SMP
], [NAME, VERSION], [ ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [
/(vlc) media player - version ([\w\.]+)/i, // VLC Videolan /(vlc) media player - version ([\w\.]+)/i, // VLC Videolan
/(vlc)\/([\w\.-]+)/i, /(vlc)\/([\w\.-]+)/i,
/(xbmc|gvfs|xine|xmms|irapp)\/([\w\.-]+)/i, // XBMC/gvfs/Xine/XMMS/irapp /(xbmc|gvfs|xine|xmms|irapp)\/([\w\.-]+)/i, // XBMC/gvfs/Xine/XMMS/irapp
/(foobar2000)\/([\d\.]+)/i, // Foobar2000 /(foobar2000)\/([\d\.]+)/i, // Foobar2000
/(itunes)\/([\d\.]+)/i // iTunes /(itunes)\/([\d\.]+)/i // iTunes
], [NAME, VERSION], [ ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [
/(wmplayer)\/([\w\.-]+)/i, // Windows Media Player /(wmplayer)\/([\w\.-]+)/i, // Windows Media Player
/(windows-media-player)\/([\w\.-]+)/i /(windows-media-player)\/([\w\.-]+)/i
], [[NAME, /-/g, ' '], VERSION], [ ], [[NAME, /-/g, ' '], VERSION, [TYPE, MEDIAPLAYER]], [
/windows\/([\w\.-]+) upnp\/[\d\.]+ dlnadoc\/[\d\.]+ (home media server)/i, /windows\/([\w\.-]+) upnp\/[\d\.]+ dlnadoc\/[\d\.]+ (home media server)/i,
// Windows Media Server // Windows Media Server
], [VERSION, [NAME, 'Windows']], [ ], [VERSION, [NAME, 'Windows'], [TYPE, MEDIAPLAYER]], [
/(com\.riseupradioalarm)\/([\d\.]*)/i // RiseUP Radio Alarm /(com\.riseupradioalarm)\/([\d\.]*)/i // RiseUP Radio Alarm
], [NAME, VERSION], [ ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [
/(rad.io)\s([\d\.]+)/i, // Rad.io /(rad.io)\s([\d\.]+)/i, // Rad.io
/(radio.(?:de|at|fr))\s([\d\.]+)/i /(radio.(?:de|at|fr))\s([\d\.]+)/i
], [[NAME, 'rad.io'], VERSION] ], [[NAME, 'rad.io'], VERSION, [TYPE, MEDIAPLAYER]]
] ]
}); });
@ -338,7 +347,21 @@ const Modules = Object.freeze({
] ]
}); });
//////////
// BOTS
/////////
const Bots = Object.freeze({
browser : [
...CLIs.browser,
...Crawlers.browser,
...Fetchers.browser,
...Modules.browser
]
});
export { export {
Bots,
CLIs, CLIs,
Crawlers, Crawlers,
ExtraDevices, ExtraDevices,

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////// ///////////////////////////////////////////////
/* Helpers for UAParser.js v2.0.0-beta.3 /* Helpers for UAParser.js v2.0.0-rc.1
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 */

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.0-beta.3 /* Helpers for UAParser.js v2.0.0-rc.1
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,16 +11,55 @@
/*jshint esversion: 6 */ /*jshint esversion: 6 */
import { CPU, OS, Engine } from '../enums/ua-parser-enums.mjs'; import { CPU, OS, Engine } from './enums/ua-parser-enums.mjs';
import { UAParser } from './main/ua-parser.mjs';
import { isFromEU } from 'detect-europe-js';
const isAppleSilicon = (res) => res.os.is(OS.MACOS) && res.cpu.is(CPU.ARM); 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 isChromiumBased = (res) => res.engine.is(Engine.BLINK); const isAppleSilicon = (res) => {
if (res.os.is(OS.MACOS)) {
if (res.cpu.is(CPU.ARM)) {
return true;
}
try {
const canvas = document.createElement('canvas');
const webgl = canvas.getContext('webgl2') || canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
const debug = webgl.getExtension('WEBGL_debug_renderer_info');
const renderer = webgl.getParameter(debug.UNMASKED_RENDERER_WEBGL);
if (renderer.match(/apple m\d/i)) {
return true;
}
} catch {
return false;
}
}
return false;
}
const isChromeFamily = (res) => res.engine.is(Engine.BLINK);
const isElectron = () => !!(process?.versions?.hasOwnProperty('electron') || // node.js
/ electron\//i.test(navigator?.userAgent)); // browser
const isFrozenUA = (ua) => /^Mozilla\/5\.0 \((Windows NT 10\.0; Win64; x64|Macintosh; Intel Mac OS X 10_15_7|X11; Linux x86_64|X11; CrOS x86_64 14541\.0\.0|Fuchsia|Linux; Android 10; K)\) AppleWebKit\/537\.36 \(KHTML, like Gecko\) Chrome\/\d+\.0\.0\.0 (Mobile )?Safari\/537\.36/.test(ua); const isFrozenUA = (ua) => /^Mozilla\/5\.0 \((Windows NT 10\.0; Win64; x64|Macintosh; Intel Mac OS X 10_15_7|X11; Linux x86_64|X11; CrOS x86_64 14541\.0\.0|Fuchsia|Linux; Android 10; K)\) AppleWebKit\/537\.36 \(KHTML, like Gecko\) Chrome\/\d+\.0\.0\.0 (Mobile )?Safari\/537\.36/.test(ua);
const isStandalonePWA = () => window && (window.matchMedia('(display-mode: standalone)').matches ||
// iOS
navigator.standalone ||
// Android
document.referrer.startsWith('android-app://') ||
// Windows
window.Windows ||
/trident.+(msapphost|webview)\//i.test(navigator.userAgent) ||
document.referrer.startsWith('app-info://platform/microsoft-store'));
export { export {
getDeviceVendor,
isAppleSilicon, isAppleSilicon,
isChromiumBased, isChromeFamily,
isFrozenUA isElectron,
isFromEU,
isFrozenUA,
isStandalonePWA
} }

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
/* UAParser.js v2.0.0-beta.3 /* UAParser.js v2.0.0-rc.1
Copyright © 2012-2024 Faisal Salman <f@faisalman.com> Copyright © 2012-2024 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.0-beta.3', var LIBVERSION = '2.0.0-rc.1',
EMPTY = '', EMPTY = '',
UNKNOWN = '?', UNKNOWN = '?',
FUNC_TYPE = 'function', FUNC_TYPE = 'function',

View File

@ -3,12 +3,12 @@
// Source: /src/main/ua-parser.js // Source: /src/main/ua-parser.js
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
/* UAParser.js v2.0.0-beta.3 /* UAParser.js v2.0.0-rc.1
Copyright © 2012-2024 Faisal Salman <f@faisalman.com> Copyright © 2012-2024 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.
Supports browser & node.js environment. Supports browser & node.js environment.
Demo : https://faisalman.github.io/ua-parser-js Demo : https://uaparser.dev
Source : https://github.com/faisalman/ua-parser-js */ Source : https://github.com/faisalman/ua-parser-js */
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
@ -21,7 +21,7 @@
// Constants // Constants
///////////// /////////////
var LIBVERSION = '2.0.0-beta.3', var LIBVERSION = '2.0.0-rc.1',
EMPTY = '', EMPTY = '',
UNKNOWN = '?', UNKNOWN = '?',
FUNC_TYPE = 'function', FUNC_TYPE = 'function',
@ -84,6 +84,7 @@
PREFIX_MOBILE = 'Mobile ', PREFIX_MOBILE = 'Mobile ',
SUFFIX_BROWSER = ' Browser', SUFFIX_BROWSER = ' Browser',
CHROME = 'Chrome', CHROME = 'Chrome',
CHROMECAST = 'Chromecast',
EDGE = 'Edge', EDGE = 'Edge',
FIREFOX = 'Firefox', FIREFOX = 'Firefox',
OPERA = 'Opera', OPERA = 'Opera',
@ -329,11 +330,13 @@
/(?:ms|\()(ie) ([\w\.]+)/i, // Internet Explorer /(?:ms|\()(ie) ([\w\.]+)/i, // Internet Explorer
// Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon // Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon
/(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|quark|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar)\/([-\w\.]+)/i, /(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio)\/([-\w\.]+)/i,
// Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio
/(heytap|ovi)browser\/([\d\.]+)/i, // HeyTap/Ovi /(heytap|ovi)browser\/([\d\.]+)/i, // HeyTap/Ovi
/(weibo)__([\d\.]+)/i // Weibo /(weibo)__([\d\.]+)/i // Weibo
], [NAME, VERSION], [ ], [NAME, VERSION], [
/quark(?:pc)?\/([-\w\.]+)/i // Quark
], [VERSION, [NAME, 'Quark']], [
/\bddg\/([\w\.]+)/i // DuckDuckGo /\bddg\/([\w\.]+)/i // DuckDuckGo
], [VERSION, [NAME, 'DuckDuckGo']], [ ], [VERSION, [NAME, 'DuckDuckGo']], [
/(?:\buc? ?browser|(?:juc.+)ucweb)[\/ ]?([\w\.]+)/i // UCBrowser /(?:\buc? ?browser|(?:juc.+)ucweb)[\/ ]?([\w\.]+)/i // UCBrowser
@ -499,8 +502,8 @@
// Samsung // Samsung
/\b(sch-i[89]0\d|shw-m380s|sm-[ptx]\w{2,4}|gt-[pn]\d{2,4}|sgh-t8[56]9|nexus 10)/i /\b(sch-i[89]0\d|shw-m380s|sm-[ptx]\w{2,4}|gt-[pn]\d{2,4}|sgh-t8[56]9|nexus 10)/i
], [MODEL, [VENDOR, SAMSUNG], [TYPE, TABLET]], [ ], [MODEL, [VENDOR, SAMSUNG], [TYPE, TABLET]], [
/\b((?:s[cgp]h|gt|sm)-\w+|sc[g-]?[\d]+a?|galaxy nexus)/i, /\b((?:s[cgp]h|gt|sm)-(?![lr])\w+|sc[g-]?[\d]+a?|galaxy nexus)/i,
/samsung[- ]([-\w]+)/i, /samsung[- ]((?!sm-[lr])[-\w]+)/i,
/sec-(sgh\w+)/i /sec-(sgh\w+)/i
], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [ ], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [
@ -531,7 +534,7 @@
/\b(hm[-_ ]?note?[_ ]?(?:\d\w)?) bui/i, // Xiaomi Hongmi /\b(hm[-_ ]?note?[_ ]?(?:\d\w)?) bui/i, // Xiaomi Hongmi
/\b(redmi[\-_ ]?(?:note|k)?[\w_ ]+)(?: bui|\))/i, // Xiaomi Redmi /\b(redmi[\-_ ]?(?:note|k)?[\w_ ]+)(?: bui|\))/i, // Xiaomi Redmi
/oid[^\)]+; (m?[12][0-389][01]\w{3,6}[c-y])( bui|; wv|\))/i, // Xiaomi Redmi 'numeric' models /oid[^\)]+; (m?[12][0-389][01]\w{3,6}[c-y])( bui|; wv|\))/i, // Xiaomi Redmi 'numeric' models
/\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note lte|max|cc)?[_ ]?(?:\d?\w?)[_ ]?(?:plus|se|lite)?)(?: bui|\))/i // Xiaomi Mi /\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note lte|max|cc)?[_ ]?(?:\d?\w?)[_ ]?(?:plus|se|lite|pro)?)(?: bui|\))/i // Xiaomi Mi
], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [ ], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [
/oid[^\)]+; (2\d{4}(283|rpbf)[cgl])( bui|\))/i, // Redmi Pad /oid[^\)]+; (2\d{4}(283|rpbf)[cgl])( bui|\))/i, // Redmi Pad
/\b(mi[-_ ]?(?:pad)(?:[\w_ ]+))(?: bui|\))/i // Mi Pad tablets /\b(mi[-_ ]?(?:pad)(?:[\w_ ]+))(?: bui|\))/i // Mi Pad tablets
@ -599,7 +602,7 @@
// Amazon // Amazon
/(alexa)webm/i, /(alexa)webm/i,
/(kf[a-z]{2}wi|aeo[c-r]{2})( bui|\))/i, // Kindle Fire without Silk / Echo Show /(kf[a-z]{2}wi|aeo(?!bc)\w\w)( bui|\))/i, // Kindle Fire without Silk / Echo Show
/(kf[a-z]+)( bui|\)).+silk\//i // Kindle Fire HD /(kf[a-z]+)( bui|\)).+silk\//i // Kindle Fire HD
], [MODEL, [VENDOR, AMAZON], [TYPE, TABLET]], [ ], [MODEL, [VENDOR, AMAZON], [TYPE, TABLET]], [
/((?:sd|kf)[0349hijorstuw]+)( bui|\)).+silk\//i // Fire Phone /((?:sd|kf)[0349hijorstuw]+)( bui|\)).+silk\//i // Fire Phone
@ -628,6 +631,17 @@
/(alcatel|geeksphone|nexian|panasonic(?!(?:;|\.))|sony(?!-bra))[-_ ]?([-\w]*)/i // Alcatel/GeeksPhone/Nexian/Panasonic/Sony /(alcatel|geeksphone|nexian|panasonic(?!(?:;|\.))|sony(?!-bra))[-_ ]?([-\w]*)/i // Alcatel/GeeksPhone/Nexian/Panasonic/Sony
], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [ ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [
// TCL
/tcl (xess p17aa)/i,
/droid [\w\.]+; ((?:8[14]9[16]|9(?:0(?:48|60|8[01])|1(?:3[27]|66)|2(?:6[69]|9[56])|466))[gqswx])(_\w(\w|\w\w))?(\)| bui)/i
], [MODEL, [VENDOR, 'TCL'], [TYPE, TABLET]], [
/droid [\w\.]+; (418(?:7d|8v)|5087z|5102l|61(?:02[dh]|25[adfh]|27[ai]|56[dh]|59k|65[ah])|a509dl|t(?:43(?:0w|1[adepqu])|50(?:6d|7[adju])|6(?:09dl|10k|12b|71[efho]|76[hjk])|7(?:66[ahju]|67[hw]|7[045][bh]|71[hk]|73o|76[ho]|79w|81[hks]?|82h|90[bhsy]|99b)|810[hs]))(_\w(\w|\w\w))?(\)| bui)/i
], [MODEL, [VENDOR, 'TCL'], [TYPE, MOBILE]], [
// itel
/(itel) ((\w+))/i
], [[VENDOR, lowerize], MODEL, [TYPE, strMapper, { 'tablet' : ['p10001l', 'w7001'], '*' : 'mobile' }]], [
// Acer // Acer
/droid.+; ([ab][1-7]-?[0178a]\d\d?)/i /droid.+; ([ab][1-7]-?[0178a]\d\d?)/i
], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [ ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [
@ -641,6 +655,10 @@
/; ((?:power )?armor(?:[\w ]{0,8}))(?: bui|\))/i /; ((?:power )?armor(?:[\w ]{0,8}))(?: bui|\))/i
], [MODEL, [VENDOR, 'Ulefone'], [TYPE, MOBILE]], [ ], [MODEL, [VENDOR, 'Ulefone'], [TYPE, MOBILE]], [
// Nothing
/droid.+; (a(?:015|06[35]|142p?))/i
], [MODEL, [VENDOR, 'Nothing'], [TYPE, MOBILE]], [
// MIXED // MIXED
/(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron|infinix|tecno)[-_ ]?([-\w]*)/i, /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron|infinix|tecno)[-_ ]?([-\w]*)/i,
// BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron
@ -685,8 +703,14 @@
], [[VENDOR, LG], [TYPE, SMARTTV]], [ ], [[VENDOR, LG], [TYPE, SMARTTV]], [
/(apple) ?tv/i // Apple TV /(apple) ?tv/i // Apple TV
], [VENDOR, [MODEL, APPLE+' TV'], [TYPE, SMARTTV]], [ ], [VENDOR, [MODEL, APPLE+' TV'], [TYPE, SMARTTV]], [
/crkey/i // Google Chromecast /crkey.*devicetype\/chromecast/i // Google Chromecast Third Generation
], [[MODEL, CHROME+'cast'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [ ], [[MODEL, CHROMECAST+' Third Generation'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [
/crkey.*devicetype\/([^/]*)/i // Google Chromecast with specific device type
], [[MODEL, /^/, 'Chromecast '], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [
/fuchsia.*crkey/i // Google Chromecast Nest Hub
], [[MODEL, CHROMECAST+' Nest Hub'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [
/crkey/i // Google Chromecast, Linux-based or unknown
], [[MODEL, CHROMECAST], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [
/droid.+aft(\w+)( bui|\))/i // Fire TV /droid.+aft(\w+)( bui|\))/i // Fire TV
], [MODEL, [VENDOR, AMAZON], [TYPE, SMARTTV]], [ ], [MODEL, [VENDOR, AMAZON], [TYPE, SMARTTV]], [
/\(dtv[\);].+(aquos)/i, /\(dtv[\);].+(aquos)/i,
@ -722,6 +746,8 @@
// WEARABLES // WEARABLES
/////////////////// ///////////////////
/\b(sm-[lr]\d\d[05][fnuw]?s?)\b/i // Samsung Galaxy Watch
], [MODEL, [VENDOR, SAMSUNG], [TYPE, WEARABLE]], [
/((pebble))app/i // Pebble /((pebble))app/i // Pebble
], [VENDOR, MODEL, [TYPE, WEARABLE]], [ ], [VENDOR, MODEL, [TYPE, WEARABLE]], [
/(watch)(?: ?os[,\/]|\d,\d\/)[\d\.]+/i // Apple Watch /(watch)(?: ?os[,\/]|\d,\d\/)[\d\.]+/i // Apple Watch
@ -735,7 +761,9 @@
/droid.+; (glass) \d/i // Google Glass /droid.+; (glass) \d/i // Google Glass
], [MODEL, [VENDOR, GOOGLE], [TYPE, XR]], [ ], [MODEL, [VENDOR, GOOGLE], [TYPE, XR]], [
/(quest( \d| pro)?)/i // Oculus Quest /(pico) (4|neo3(?: link|pro)?)/i // Pico
], [VENDOR, MODEL, [TYPE, XR]], [
/; (quest( \d| pro)?)/i // Oculus Quest
], [MODEL, [VENDOR, FACEBOOK], [TYPE, XR]], [ ], [MODEL, [VENDOR, FACEBOOK], [TYPE, XR]], [
/////////////////// ///////////////////
@ -768,6 +796,9 @@
/windows.+ edge\/([\w\.]+)/i // EdgeHTML /windows.+ edge\/([\w\.]+)/i // EdgeHTML
], [VERSION, [NAME, EDGE+'HTML']], [ ], [VERSION, [NAME, EDGE+'HTML']], [
/(arkweb)\/([\w\.]+)/i // ArkWeb
], [NAME, VERSION], [
/webkit\/537\.36.+chrome\/(?!27)([\w\.]+)/i // Blink /webkit\/537\.36.+chrome\/(?!27)([\w\.]+)/i // Blink
], [VERSION, [NAME, 'Blink']], [ ], [VERSION, [NAME, 'Blink']], [
@ -804,10 +835,22 @@
/(macintosh|mac_powerpc\b)(?!.+haiku)/i // Mac OS /(macintosh|mac_powerpc\b)(?!.+haiku)/i // Mac OS
], [[NAME, 'macOS'], [VERSION, /_/g, '.']], [ ], [[NAME, 'macOS'], [VERSION, /_/g, '.']], [
// Google Chromecast
/android ([\d\.]+).*crkey/i // Google Chromecast, Android-based
], [VERSION, [NAME, CHROMECAST + ' Android']], [
/fuchsia.*crkey\/([\d\.]+)/i // Google Chromecast, Fuchsia-based
], [VERSION, [NAME, CHROMECAST + ' Fuchsia']], [
/crkey\/([\d\.]+).*devicetype\/smartspeaker/i // Google Chromecast, Linux-based Smart Speaker
], [VERSION, [NAME, CHROMECAST + ' SmartSpeaker']], [
/linux.*crkey\/([\d\.]+)/i // Google Chromecast, Legacy Linux-based
], [VERSION, [NAME, CHROMECAST + ' Linux']], [
/crkey\/([\d\.]+)/i // Google Chromecast, unknown
], [VERSION, [NAME, CHROMECAST]], [
// Mobile OSes // Mobile OSes
/droid ([\w\.]+)\b.+(android[- ]x86|harmonyos)/i // Android-x86/HarmonyOS /droid ([\w\.]+)\b.+(android[- ]x86|harmonyos)/i // Android-x86/HarmonyOS
], [VERSION, NAME], [ // Android/WebOS/QNX/Bada/RIM/Maemo/MeeGo/Sailfish OS ], [VERSION, NAME], [ // Android/WebOS/QNX/Bada/RIM/Maemo/MeeGo/Sailfish OS/OpenHarmony
/(android|webos|qnx|bada|rim tablet os|maemo|meego|sailfish)[-\/ ]?([\w\.]*)/i, /(android|webos|qnx|bada|rim tablet os|maemo|meego|sailfish|openharmony)[-\/ ]?([\w\.]*)/i,
/(blackberry)\w*\/([\w\.]*)/i, // Blackberry /(blackberry)\w*\/([\w\.]*)/i, // Blackberry
/(tizen|kaios)[\/ ]([\w\.]+)/i, // Tizen/KaiOS /(tizen|kaios)[\/ ]([\w\.]+)/i, // Tizen/KaiOS
/\((series40);/i // Series 40 /\((series40);/i // Series 40
@ -824,9 +867,7 @@
/watch(?: ?os[,\/]|\d,\d\/)([\d\.]+)/i // watchOS /watch(?: ?os[,\/]|\d,\d\/)([\d\.]+)/i // watchOS
], [VERSION, [NAME, 'watchOS']], [ ], [VERSION, [NAME, 'watchOS']], [
// Google Chromecast // Google ChromeOS
/crkey\/([\d\.]+)/i // Google Chromecast
], [VERSION, [NAME, CHROME+'cast']], [
/(cros) [\w]+(?:\)| ([\w\.]+)\b)/i // Chromium OS /(cros) [\w]+(?:\)| ([\w\.]+)\b)/i // Chromium OS
], [[NAME, "Chrome OS"], VERSION],[ ], [[NAME, "Chrome OS"], VERSION],[
@ -838,6 +879,7 @@
// Console // Console
/(nintendo|playstation) (\w+)/i, // Nintendo/Playstation /(nintendo|playstation) (\w+)/i, // Nintendo/Playstation
/(xbox); +xbox ([^\);]+)/i, // Microsoft Xbox (360, One, X, S, Series X, Series S) /(xbox); +xbox ([^\);]+)/i, // Microsoft Xbox (360, One, X, S, Series X, Series S)
/(pico) .+os([\w\.]+)/i, // Pico
// Other // Other
/\b(joli|palm)\b ?(?:os)?\/?([\w\.]*)/i, // Joli/Palm /\b(joli|palm)\b ?(?:os)?\/?([\w\.]*)/i, // Joli/Palm