diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f2fa9b..d1f9ac6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,27 @@ --- +## Version 2.0.4 + +- Add new browser: Edge WebView, Edge WebView2 +- Add new device vendor: Lava, Retroid, Vizio +- Add new OS: ArcaOS, Knoppix, Xubuntu, Windows CE, Windows RT +- Improve device detection: Google Pixel & Pixelbook Series, HMD, Infinix, LG WebOS TV, Motorola, Nothing, OnePlus, Sony, Tecno +- Improve OS detection: AIX, Arch, Fuchsia, Haiku, HarmonyOS, Mint, MorphOS, Solaris, Windows +- Improve `withClientHints()` browser naming adjustments: `Microsoft Edge WebView2` => `Edge WebView2` +- Identify device that uses Firefox Reality / Wolvic as `xr` +- Identify device with large screen as `smarttv` +- Identify Windows CE & Windows RT as distinct OS variants +- `extensions` submodule: + - Remove lookbehind assertion to ensure regex compatibility + - Add new crawlers: ChatGLM, Daum, iAskBot, Onespot, Qwantbot, Startpage + - Add new emails: Apple's Mail, DaumMail, Polymail, ProtonMail, SparkDesktop, Zimbra, ZohoMail-Desktop + - Add new fetchers: Iframely, MistralAI-User, Perplexity-User + - Add new inApps: Discord, Evernote, Figma, Flipboard, Mattermost, Notion, Postman, Rambox, Rocket.Chat, Microsoft Teams, TikTok Lite, VS Code + - Add new libraries: AdobeAIR, aiohttp, nutch, httpx, urllib3 +- `enum` submodule: + - Fix mistakenly placed `BLU` categorized as browser name instead of device vendor + ## Version 2.0.3 - Add new browser: Dooble, Ecosia, LG Browser, Otter, qutebrowser, Surf diff --git a/dist/ua-parser.min.js b/dist/ua-parser.min.js index c682ce7..3edc995 100644 --- a/dist/ua-parser.min.js +++ b/dist/ua-parser.min.js @@ -1,4 +1,4 @@ -/* UAParser.js v2.0.3 +/* UAParser.js v2.0.4 Copyright © 2012-2025 Faisal Salman UAParser.js PRO Enterprise License */ -(function(window,undefined){"use strict";var LIBVERSION="2.0.3",UA_MAX_LENGTH=500,USER_AGENT="user-agent",EMPTY="",UNKNOWN="?",FUNC_TYPE="function",UNDEF_TYPE="undefined",OBJ_TYPE="object",STR_TYPE="string",UA_BROWSER="browser",UA_CPU="cpu",UA_DEVICE="device",UA_ENGINE="engine",UA_OS="os",UA_RESULT="result",NAME="name",TYPE="type",VENDOR="vendor",VERSION="version",ARCHITECTURE="architecture",MAJOR="major",MODEL="model",CONSOLE="console",MOBILE="mobile",TABLET="tablet",SMARTTV="smarttv",WEARABLE="wearable",XR="xr",EMBEDDED="embedded",INAPP="inapp",BRANDS="brands",FORMFACTORS="formFactors",FULLVERLIST="fullVersionList",PLATFORM="platform",PLATFORMVER="platformVersion",BITNESS="bitness",CH_HEADER="sec-ch-ua",CH_HEADER_FULL_VER_LIST=CH_HEADER+"-full-version-list",CH_HEADER_ARCH=CH_HEADER+"-arch",CH_HEADER_BITNESS=CH_HEADER+"-"+BITNESS,CH_HEADER_FORM_FACTORS=CH_HEADER+"-form-factors",CH_HEADER_MOBILE=CH_HEADER+"-"+MOBILE,CH_HEADER_MODEL=CH_HEADER+"-"+MODEL,CH_HEADER_PLATFORM=CH_HEADER+"-"+PLATFORM,CH_HEADER_PLATFORM_VER=CH_HEADER_PLATFORM+"-version",CH_ALL_VALUES=[BRANDS,FULLVERLIST,MOBILE,MODEL,PLATFORM,PLATFORMVER,ARCHITECTURE,FORMFACTORS,BITNESS],AMAZON="Amazon",APPLE="Apple",ASUS="ASUS",BLACKBERRY="BlackBerry",GOOGLE="Google",HUAWEI="Huawei",LENOVO="Lenovo",HONOR="Honor",LG="LG",MICROSOFT="Microsoft",MOTOROLA="Motorola",NVIDIA="Nvidia",ONEPLUS="OnePlus",OPPO="OPPO",SAMSUNG="Samsung",SHARP="Sharp",SONY="Sony",XIAOMI="Xiaomi",ZEBRA="Zebra",CHROME="Chrome",CHROMIUM="Chromium",CHROMECAST="Chromecast",EDGE="Edge",FIREFOX="Firefox",OPERA="Opera",FACEBOOK="Facebook",SOGOU="Sogou",PREFIX_MOBILE="Mobile ",SUFFIX_BROWSER=" Browser",WINDOWS="Windows";var isWindow=typeof window!==UNDEF_TYPE,NAVIGATOR=isWindow&&window.navigator?window.navigator:undefined,NAVIGATOR_UADATA=NAVIGATOR&&NAVIGATOR.userAgentData?NAVIGATOR.userAgentData:undefined;var extend=function(defaultRgx,extensions){var mergedRgx={};var extraRgx=extensions;if(!isExtensions(extensions)){extraRgx={};for(var i in extensions){for(var j in extensions[i]){extraRgx[j]=extensions[i][j].concat(extraRgx[j]?extraRgx[j]:[])}}}for(var k in defaultRgx){mergedRgx[k]=extraRgx[k]&&extraRgx[k].length%2===0?extraRgx[k].concat(defaultRgx[k]):defaultRgx[k]}return mergedRgx},enumerize=function(arr){var enums={};for(var i=0;i0){for(var i in str1){if(lowerize(str1[i])==lowerize(str2))return true}return false}return isString(str1)?lowerize(str2).indexOf(lowerize(str1))!==-1:false},isExtensions=function(obj,deep){for(var prop in obj){return/^(browser|cpu|device|engine|os)$/.test(prop)||(deep?isExtensions(obj[prop]):false)}},isString=function(val){return typeof val===STR_TYPE},itemListToArray=function(header){if(!header)return undefined;var arr=[];var tokens=strip(/\\?\"/g,header).split(",");for(var i=0;i-1){var token=trim(tokens[i]).split(";v=");arr[i]={brand:token[0],version:token[1]}}else{arr[i]=trim(tokens[i])}}return arr},lowerize=function(str){return isString(str)?str.toLowerCase():str},majorize=function(version){return isString(version)?strip(/[^\d\.]/g,version).split(".")[0]:undefined},setProps=function(arr){for(var i in arr){var propName=arr[i];if(typeof propName==OBJ_TYPE&&propName.length==2){this[propName[0]]=propName[1]}else{this[propName]=undefined}}return this},strip=function(pattern,str){return isString(str)?str.replace(pattern,EMPTY):str},stripQuotes=function(str){return strip(/\\?\"/g,str)},trim=function(str,len){if(isString(str)){str=strip(/^\s\s*/,str);return typeof len===UNDEF_TYPE?str:str.substring(0,UA_MAX_LENGTH)}};var rgxMapper=function(ua,arrays){if(!ua||!arrays)return;var i=0,j,k,p,q,matches,match;while(i0){if(q.length===2){if(typeof q[1]==FUNC_TYPE){this[q[0]]=q[1].call(this,match)}else{this[q[0]]=q[1]}}else if(q.length===3){if(typeof q[1]===FUNC_TYPE&&!(q[1].exec&&q[1].test)){this[q[0]]=match?q[1].call(this,match,q[2]):undefined}else{this[q[0]]=match?match.replace(q[1],q[2]):undefined}}else if(q.length===4){this[q[0]]=match?q[3].call(this,match.replace(q[1],q[2])):undefined}}else{this[q]=match?match:undefined}}}}i+=2}},strMapper=function(str,map){for(var i in map){if(typeof map[i]===OBJ_TYPE&&map[i].length>0){for(var j=0;j2){this.set(MODEL,"iPad").set(TYPE,TABLET)}break;case UA_OS:if(!this.get(NAME)&&NAVIGATOR_UADATA&&NAVIGATOR_UADATA[PLATFORM]){this.set(NAME,NAVIGATOR_UADATA[PLATFORM])}break;case UA_RESULT:var data=this.data;var detect=function(itemType){return data[itemType].getItem().detectFeature().get()};this.set(UA_BROWSER,detect(UA_BROWSER)).set(UA_CPU,detect(UA_CPU)).set(UA_DEVICE,detect(UA_DEVICE)).set(UA_ENGINE,detect(UA_ENGINE)).set(UA_OS,detect(UA_OS))}}return this};this.parseUA=function(){if(this.itemType!=UA_RESULT){rgxMapper.call(this.data,this.ua,this.rgxMap)}if(this.itemType==UA_BROWSER){this.set(MAJOR,majorize(this.get(VERSION)))}return this};this.parseCH=function(){var uaCH=this.uaCH,rgxMap=this.rgxMap;switch(this.itemType){case UA_BROWSER:case UA_ENGINE:var brands=uaCH[FULLVERLIST]||uaCH[BRANDS],prevName;if(brands){for(var i in brands){var brandName=brands[i].brand||brands[i],brandVersion=brands[i].version;if(this.itemType==UA_BROWSER&&!/not.a.brand/i.test(brandName)&&(!prevName||/chrom/i.test(prevName)&&brandName!=CHROMIUM)){brandName=strMapper(brandName,{Chrome:"Google Chrome",Edge:"Microsoft Edge","Chrome WebView":"Android WebView","Chrome Headless":"HeadlessChrome","Huawei Browser":"HuaweiBrowser","MIUI Browser":"Miui Browser","Opera Mobi":"OperaMobile",Yandex:"YaBrowser"});this.set(NAME,brandName).set(VERSION,brandVersion).set(MAJOR,majorize(brandVersion));prevName=brandName}if(this.itemType==UA_ENGINE&&brandName==CHROMIUM){this.set(VERSION,brandVersion)}}}break;case UA_CPU:var archName=uaCH[ARCHITECTURE];if(archName){if(archName&&uaCH[BITNESS]=="64")archName+="64";rgxMapper.call(this.data,archName+";",rgxMap)}break;case UA_DEVICE:if(uaCH[MOBILE]){this.set(TYPE,MOBILE)}if(uaCH[MODEL]){this.set(MODEL,uaCH[MODEL]);if(!this.get(TYPE)||!this.get(VENDOR)){var reParse={};rgxMapper.call(reParse,"droid 9; "+uaCH[MODEL]+")",rgxMap);if(!this.get(TYPE)&&!!reParse.type){this.set(TYPE,reParse.type)}if(!this.get(VENDOR)&&!!reParse.vendor){this.set(VENDOR,reParse.vendor)}}}if(uaCH[FORMFACTORS]){var ff;if(typeof uaCH[FORMFACTORS]!=="string"){var idx=0;while(!ff&&idx=13?"11":"10";this.set(NAME,osName).set(VERSION,osVersion)}if(this.get(NAME)==WINDOWS&&uaCH[MODEL]=="Xbox"){this.set(NAME,"Xbox").set(VERSION,undefined)}break;case UA_RESULT:var data=this.data;var parse=function(itemType){return data[itemType].getItem().setCH(uaCH).parseCH().get()};this.set(UA_BROWSER,parse(UA_BROWSER)).set(UA_CPU,parse(UA_CPU)).set(UA_DEVICE,parse(UA_DEVICE)).set(UA_ENGINE,parse(UA_ENGINE)).set(UA_OS,parse(UA_OS))}return this};setProps.call(this,[["itemType",itemType],["ua",ua],["uaCH",uaCH],["rgxMap",rgxMap],["data",createIData(this,itemType)]]);return this}function UAParser(ua,extensions,headers){if(typeof ua===OBJ_TYPE){if(isExtensions(ua,true)){if(typeof extensions===OBJ_TYPE){headers=extensions}extensions=ua}else{headers=ua;extensions=undefined}ua=undefined}else if(typeof ua===STR_TYPE&&!isExtensions(extensions,true)){headers=extensions;extensions=undefined}if(headers&&typeof headers.append===FUNC_TYPE){var kv={};headers.forEach(function(v,k){kv[k]=v});headers=kv}if(!(this instanceof UAParser)){return new UAParser(ua,extensions,headers).getResult()}var userAgent=typeof ua===STR_TYPE?ua:headers&&headers[USER_AGENT]?headers[USER_AGENT]:NAVIGATOR&&NAVIGATOR.userAgent?NAVIGATOR.userAgent:EMPTY,httpUACH=new UACHData(headers,true),regexMap=extensions?extend(defaultRegexes,extensions):defaultRegexes,createItemFunc=function(itemType){if(itemType==UA_RESULT){return function(){return new UAItem(itemType,userAgent,regexMap,httpUACH).set("ua",userAgent).set(UA_BROWSER,this.getBrowser()).set(UA_CPU,this.getCPU()).set(UA_DEVICE,this.getDevice()).set(UA_ENGINE,this.getEngine()).set(UA_OS,this.getOS()).get()}}else{return function(){return new UAItem(itemType,userAgent,regexMap[itemType],httpUACH).parseUA().get()}}};setProps.call(this,[["getBrowser",createItemFunc(UA_BROWSER)],["getCPU",createItemFunc(UA_CPU)],["getDevice",createItemFunc(UA_DEVICE)],["getEngine",createItemFunc(UA_ENGINE)],["getOS",createItemFunc(UA_OS)],["getResult",createItemFunc(UA_RESULT)],["getUA",function(){return userAgent}],["setUA",function(ua){if(isString(ua))userAgent=ua.length>UA_MAX_LENGTH?trim(ua,UA_MAX_LENGTH):ua;return this}]]).setUA(userAgent);return this}UAParser.VERSION=LIBVERSION;UAParser.BROWSER=enumerize([NAME,VERSION,MAJOR,TYPE]);UAParser.CPU=enumerize([ARCHITECTURE]);UAParser.DEVICE=enumerize([MODEL,VENDOR,TYPE,CONSOLE,MOBILE,SMARTTV,TABLET,WEARABLE,EMBEDDED]);UAParser.ENGINE=UAParser.OS=enumerize([NAME,VERSION]);if(typeof exports!==UNDEF_TYPE){if(typeof module!==UNDEF_TYPE&&module.exports){exports=module.exports=UAParser}exports.UAParser=UAParser}else{if(typeof define===FUNC_TYPE&&define.amd){define(function(){return UAParser})}else if(isWindow){window.UAParser=UAParser}}var $=isWindow&&(window.jQuery||window.Zepto);if($&&!$.ua){var parser=new UAParser;$.ua=parser.getResult();$.ua.get=function(){return parser.getUA()};$.ua.set=function(ua){parser.setUA(ua);var result=parser.getResult();for(var prop in result){$.ua[prop]=result[prop]}}}})(typeof window==="object"?window:this); \ No newline at end of file +(function(window,undefined){"use strict";var LIBVERSION="2.0.4",UA_MAX_LENGTH=500,USER_AGENT="user-agent",EMPTY="",UNKNOWN="?",FUNC_TYPE="function",UNDEF_TYPE="undefined",OBJ_TYPE="object",STR_TYPE="string",UA_BROWSER="browser",UA_CPU="cpu",UA_DEVICE="device",UA_ENGINE="engine",UA_OS="os",UA_RESULT="result",NAME="name",TYPE="type",VENDOR="vendor",VERSION="version",ARCHITECTURE="architecture",MAJOR="major",MODEL="model",CONSOLE="console",MOBILE="mobile",TABLET="tablet",SMARTTV="smarttv",WEARABLE="wearable",XR="xr",EMBEDDED="embedded",INAPP="inapp",BRANDS="brands",FORMFACTORS="formFactors",FULLVERLIST="fullVersionList",PLATFORM="platform",PLATFORMVER="platformVersion",BITNESS="bitness",CH_HEADER="sec-ch-ua",CH_HEADER_FULL_VER_LIST=CH_HEADER+"-full-version-list",CH_HEADER_ARCH=CH_HEADER+"-arch",CH_HEADER_BITNESS=CH_HEADER+"-"+BITNESS,CH_HEADER_FORM_FACTORS=CH_HEADER+"-form-factors",CH_HEADER_MOBILE=CH_HEADER+"-"+MOBILE,CH_HEADER_MODEL=CH_HEADER+"-"+MODEL,CH_HEADER_PLATFORM=CH_HEADER+"-"+PLATFORM,CH_HEADER_PLATFORM_VER=CH_HEADER_PLATFORM+"-version",CH_ALL_VALUES=[BRANDS,FULLVERLIST,MOBILE,MODEL,PLATFORM,PLATFORMVER,ARCHITECTURE,FORMFACTORS,BITNESS],AMAZON="Amazon",APPLE="Apple",ASUS="ASUS",BLACKBERRY="BlackBerry",GOOGLE="Google",HUAWEI="Huawei",LENOVO="Lenovo",HONOR="Honor",LG="LG",MICROSOFT="Microsoft",MOTOROLA="Motorola",NVIDIA="Nvidia",ONEPLUS="OnePlus",OPPO="OPPO",SAMSUNG="Samsung",SHARP="Sharp",SONY="Sony",XIAOMI="Xiaomi",ZEBRA="Zebra",CHROME="Chrome",CHROMIUM="Chromium",CHROMECAST="Chromecast",EDGE="Edge",FIREFOX="Firefox",OPERA="Opera",FACEBOOK="Facebook",SOGOU="Sogou",PREFIX_MOBILE="Mobile ",SUFFIX_BROWSER=" Browser",WINDOWS="Windows";var isWindow=typeof window!==UNDEF_TYPE,NAVIGATOR=isWindow&&window.navigator?window.navigator:undefined,NAVIGATOR_UADATA=NAVIGATOR&&NAVIGATOR.userAgentData?NAVIGATOR.userAgentData:undefined;var extend=function(defaultRgx,extensions){var mergedRgx={};var extraRgx=extensions;if(!isExtensions(extensions)){extraRgx={};for(var i in extensions){for(var j in extensions[i]){extraRgx[j]=extensions[i][j].concat(extraRgx[j]?extraRgx[j]:[])}}}for(var k in defaultRgx){mergedRgx[k]=extraRgx[k]&&extraRgx[k].length%2===0?extraRgx[k].concat(defaultRgx[k]):defaultRgx[k]}return mergedRgx},enumerize=function(arr){var enums={};for(var i=0;i0){for(var i in str1){if(lowerize(str2)==lowerize(str1[i]))return true}return false}return isString(str1)?lowerize(str2)==lowerize(str1):false},isExtensions=function(obj,deep){for(var prop in obj){return/^(browser|cpu|device|engine|os)$/.test(prop)||(deep?isExtensions(obj[prop]):false)}},isString=function(val){return typeof val===STR_TYPE},itemListToArray=function(header){if(!header)return undefined;var arr=[];var tokens=strip(/\\?\"/g,header).split(",");for(var i=0;i-1){var token=trim(tokens[i]).split(";v=");arr[i]={brand:token[0],version:token[1]}}else{arr[i]=trim(tokens[i])}}return arr},lowerize=function(str){return isString(str)?str.toLowerCase():str},majorize=function(version){return isString(version)?strip(/[^\d\.]/g,version).split(".")[0]:undefined},setProps=function(arr){for(var i in arr){var propName=arr[i];if(typeof propName==OBJ_TYPE&&propName.length==2){this[propName[0]]=propName[1]}else{this[propName]=undefined}}return this},strip=function(pattern,str){return isString(str)?str.replace(pattern,EMPTY):str},stripQuotes=function(str){return strip(/\\?\"/g,str)},trim=function(str,len){if(isString(str)){str=strip(/^\s\s*/,str);return typeof len===UNDEF_TYPE?str:str.substring(0,UA_MAX_LENGTH)}};var rgxMapper=function(ua,arrays){if(!ua||!arrays)return;var i=0,j,k,p,q,matches,match;while(i0){if(q.length===2){if(typeof q[1]==FUNC_TYPE){this[q[0]]=q[1].call(this,match)}else{this[q[0]]=q[1]}}else if(q.length>=3){if(typeof q[1]===FUNC_TYPE&&!(q[1].exec&&q[1].test)){if(q.length>3){this[q[0]]=match?q[1].apply(this,q.slice(2)):undefined}else{this[q[0]]=match?q[1].call(this,match,q[2]):undefined}}else{if(q.length==3){this[q[0]]=match?match.replace(q[1],q[2]):undefined}else if(q.length==4){this[q[0]]=match?q[3].call(this,match.replace(q[1],q[2])):undefined}else if(q.length>4){this[q[0]]=match?q[3].apply(this,[match.replace(q[1],q[2])].concat(q.slice(4))):undefined}}}}else{this[q]=match?match:undefined}}}}i+=2}},strMapper=function(str,map){for(var i in map){if(typeof map[i]===OBJ_TYPE&&map[i].length>0){for(var j=0;j2){this.set(MODEL,"iPad").set(TYPE,TABLET)}break;case UA_OS:if(!this.get(NAME)&&NAVIGATOR_UADATA&&NAVIGATOR_UADATA[PLATFORM]){this.set(NAME,NAVIGATOR_UADATA[PLATFORM])}break;case UA_RESULT:var data=this.data;var detect=function(itemType){return data[itemType].getItem().detectFeature().get()};this.set(UA_BROWSER,detect(UA_BROWSER)).set(UA_CPU,detect(UA_CPU)).set(UA_DEVICE,detect(UA_DEVICE)).set(UA_ENGINE,detect(UA_ENGINE)).set(UA_OS,detect(UA_OS))}}return this};this.parseUA=function(){if(this.itemType!=UA_RESULT){rgxMapper.call(this.data,this.ua,this.rgxMap)}if(this.itemType==UA_BROWSER){this.set(MAJOR,majorize(this.get(VERSION)))}return this};this.parseCH=function(){var uaCH=this.uaCH,rgxMap=this.rgxMap;switch(this.itemType){case UA_BROWSER:case UA_ENGINE:var brands=uaCH[FULLVERLIST]||uaCH[BRANDS],prevName;if(brands){for(var i in brands){var brandName=brands[i].brand||brands[i],brandVersion=brands[i].version;if(this.itemType==UA_BROWSER&&!/not.a.brand/i.test(brandName)&&(!prevName||/Chrom/.test(prevName)&&brandName!=CHROMIUM||prevName==EDGE&&/WebView2/.test(brandName))){brandName=strMapper(brandName,browserHintsMap);prevName=this.get(NAME);if(!(prevName&&!/Chrom/.test(prevName)&&/Chrom/.test(brandName))){this.set(NAME,brandName).set(VERSION,brandVersion).set(MAJOR,majorize(brandVersion))}prevName=brandName}if(this.itemType==UA_ENGINE&&brandName==CHROMIUM){this.set(VERSION,brandVersion)}}}break;case UA_CPU:var archName=uaCH[ARCHITECTURE];if(archName){if(archName&&uaCH[BITNESS]=="64")archName+="64";rgxMapper.call(this.data,archName+";",rgxMap)}break;case UA_DEVICE:if(uaCH[MOBILE]){this.set(TYPE,MOBILE)}if(uaCH[MODEL]){this.set(MODEL,uaCH[MODEL]);if(!this.get(TYPE)||!this.get(VENDOR)){var reParse={};rgxMapper.call(reParse,"droid 9; "+uaCH[MODEL]+")",rgxMap);if(!this.get(TYPE)&&!!reParse.type){this.set(TYPE,reParse.type)}if(!this.get(VENDOR)&&!!reParse.vendor){this.set(VENDOR,reParse.vendor)}}}if(uaCH[FORMFACTORS]){var ff;if(typeof uaCH[FORMFACTORS]!=="string"){var idx=0;while(!ff&&idx=13?"11":"10";this.set(NAME,osName).set(VERSION,osVersion)}if(this.get(NAME)==WINDOWS&&uaCH[MODEL]=="Xbox"){this.set(NAME,"Xbox").set(VERSION,undefined)}break;case UA_RESULT:var data=this.data;var parse=function(itemType){return data[itemType].getItem().setCH(uaCH).parseCH().get()};this.set(UA_BROWSER,parse(UA_BROWSER)).set(UA_CPU,parse(UA_CPU)).set(UA_DEVICE,parse(UA_DEVICE)).set(UA_ENGINE,parse(UA_ENGINE)).set(UA_OS,parse(UA_OS))}return this};setProps.call(this,[["itemType",itemType],["ua",ua],["uaCH",uaCH],["rgxMap",rgxMap],["data",createIData(this,itemType)]]);return this}function UAParser(ua,extensions,headers){if(typeof ua===OBJ_TYPE){if(isExtensions(ua,true)){if(typeof extensions===OBJ_TYPE){headers=extensions}extensions=ua}else{headers=ua;extensions=undefined}ua=undefined}else if(typeof ua===STR_TYPE&&!isExtensions(extensions,true)){headers=extensions;extensions=undefined}if(headers&&typeof headers.append===FUNC_TYPE){var kv={};headers.forEach(function(v,k){kv[k]=v});headers=kv}if(!(this instanceof UAParser)){return new UAParser(ua,extensions,headers).getResult()}var userAgent=typeof ua===STR_TYPE?ua:headers&&headers[USER_AGENT]?headers[USER_AGENT]:NAVIGATOR&&NAVIGATOR.userAgent?NAVIGATOR.userAgent:EMPTY,httpUACH=new UACHData(headers,true),regexMap=extensions?extend(defaultRegexes,extensions):defaultRegexes,createItemFunc=function(itemType){if(itemType==UA_RESULT){return function(){return new UAItem(itemType,userAgent,regexMap,httpUACH).set("ua",userAgent).set(UA_BROWSER,this.getBrowser()).set(UA_CPU,this.getCPU()).set(UA_DEVICE,this.getDevice()).set(UA_ENGINE,this.getEngine()).set(UA_OS,this.getOS()).get()}}else{return function(){return new UAItem(itemType,userAgent,regexMap[itemType],httpUACH).parseUA().get()}}};setProps.call(this,[["getBrowser",createItemFunc(UA_BROWSER)],["getCPU",createItemFunc(UA_CPU)],["getDevice",createItemFunc(UA_DEVICE)],["getEngine",createItemFunc(UA_ENGINE)],["getOS",createItemFunc(UA_OS)],["getResult",createItemFunc(UA_RESULT)],["getUA",function(){return userAgent}],["setUA",function(ua){if(isString(ua))userAgent=ua.length>UA_MAX_LENGTH?trim(ua,UA_MAX_LENGTH):ua;return this}]]).setUA(userAgent);return this}UAParser.VERSION=LIBVERSION;UAParser.BROWSER=enumerize([NAME,VERSION,MAJOR,TYPE]);UAParser.CPU=enumerize([ARCHITECTURE]);UAParser.DEVICE=enumerize([MODEL,VENDOR,TYPE,CONSOLE,MOBILE,SMARTTV,TABLET,WEARABLE,EMBEDDED]);UAParser.ENGINE=UAParser.OS=enumerize([NAME,VERSION]);if(typeof exports!==UNDEF_TYPE){if(typeof module!==UNDEF_TYPE&&module.exports){exports=module.exports=UAParser}exports.UAParser=UAParser}else{if(typeof define===FUNC_TYPE&&define.amd){define(function(){return UAParser})}else if(isWindow){window.UAParser=UAParser}}var $=isWindow&&(window.jQuery||window.Zepto);if($&&!$.ua){var parser=new UAParser;$.ua=parser.getResult();$.ua.get=function(){return parser.getUA()};$.ua.set=function(ua){parser.setUA(ua);var result=parser.getResult();for(var prop in result){$.ua[prop]=result[prop]}}}})(typeof window==="object"?window:this); \ No newline at end of file diff --git a/dist/ua-parser.min.mjs b/dist/ua-parser.min.mjs index 4f53d4c..8e0c465 100644 --- a/dist/ua-parser.min.mjs +++ b/dist/ua-parser.min.mjs @@ -1,4 +1,4 @@ -/* UAParser.js v2.0.3 +/* UAParser.js v2.0.4 Copyright © 2012-2025 Faisal Salman UAParser.js PRO Enterprise License */ -var LIBVERSION="2.0.3",UA_MAX_LENGTH=500,USER_AGENT="user-agent",EMPTY="",UNKNOWN="?",FUNC_TYPE="function",UNDEF_TYPE="undefined",OBJ_TYPE="object",STR_TYPE="string",UA_BROWSER="browser",UA_CPU="cpu",UA_DEVICE="device",UA_ENGINE="engine",UA_OS="os",UA_RESULT="result",NAME="name",TYPE="type",VENDOR="vendor",VERSION="version",ARCHITECTURE="architecture",MAJOR="major",MODEL="model",CONSOLE="console",MOBILE="mobile",TABLET="tablet",SMARTTV="smarttv",WEARABLE="wearable",XR="xr",EMBEDDED="embedded",INAPP="inapp",BRANDS="brands",FORMFACTORS="formFactors",FULLVERLIST="fullVersionList",PLATFORM="platform",PLATFORMVER="platformVersion",BITNESS="bitness",CH_HEADER="sec-ch-ua",CH_HEADER_FULL_VER_LIST=CH_HEADER+"-full-version-list",CH_HEADER_ARCH=CH_HEADER+"-arch",CH_HEADER_BITNESS=CH_HEADER+"-"+BITNESS,CH_HEADER_FORM_FACTORS=CH_HEADER+"-form-factors",CH_HEADER_MOBILE=CH_HEADER+"-"+MOBILE,CH_HEADER_MODEL=CH_HEADER+"-"+MODEL,CH_HEADER_PLATFORM=CH_HEADER+"-"+PLATFORM,CH_HEADER_PLATFORM_VER=CH_HEADER_PLATFORM+"-version",CH_ALL_VALUES=[BRANDS,FULLVERLIST,MOBILE,MODEL,PLATFORM,PLATFORMVER,ARCHITECTURE,FORMFACTORS,BITNESS],AMAZON="Amazon",APPLE="Apple",ASUS="ASUS",BLACKBERRY="BlackBerry",GOOGLE="Google",HUAWEI="Huawei",LENOVO="Lenovo",HONOR="Honor",LG="LG",MICROSOFT="Microsoft",MOTOROLA="Motorola",NVIDIA="Nvidia",ONEPLUS="OnePlus",OPPO="OPPO",SAMSUNG="Samsung",SHARP="Sharp",SONY="Sony",XIAOMI="Xiaomi",ZEBRA="Zebra",CHROME="Chrome",CHROMIUM="Chromium",CHROMECAST="Chromecast",EDGE="Edge",FIREFOX="Firefox",OPERA="Opera",FACEBOOK="Facebook",SOGOU="Sogou",PREFIX_MOBILE="Mobile ",SUFFIX_BROWSER=" Browser",WINDOWS="Windows";var isWindow=typeof window!==UNDEF_TYPE,NAVIGATOR=isWindow&&window.navigator?window.navigator:undefined,NAVIGATOR_UADATA=NAVIGATOR&&NAVIGATOR.userAgentData?NAVIGATOR.userAgentData:undefined;var extend=function(defaultRgx,extensions){var mergedRgx={};var extraRgx=extensions;if(!isExtensions(extensions)){extraRgx={};for(var i in extensions){for(var j in extensions[i]){extraRgx[j]=extensions[i][j].concat(extraRgx[j]?extraRgx[j]:[])}}}for(var k in defaultRgx){mergedRgx[k]=extraRgx[k]&&extraRgx[k].length%2===0?extraRgx[k].concat(defaultRgx[k]):defaultRgx[k]}return mergedRgx},enumerize=function(arr){var enums={};for(var i=0;i0){for(var i in str1){if(lowerize(str1[i])==lowerize(str2))return true}return false}return isString(str1)?lowerize(str2).indexOf(lowerize(str1))!==-1:false},isExtensions=function(obj,deep){for(var prop in obj){return/^(browser|cpu|device|engine|os)$/.test(prop)||(deep?isExtensions(obj[prop]):false)}},isString=function(val){return typeof val===STR_TYPE},itemListToArray=function(header){if(!header)return undefined;var arr=[];var tokens=strip(/\\?\"/g,header).split(",");for(var i=0;i-1){var token=trim(tokens[i]).split(";v=");arr[i]={brand:token[0],version:token[1]}}else{arr[i]=trim(tokens[i])}}return arr},lowerize=function(str){return isString(str)?str.toLowerCase():str},majorize=function(version){return isString(version)?strip(/[^\d\.]/g,version).split(".")[0]:undefined},setProps=function(arr){for(var i in arr){var propName=arr[i];if(typeof propName==OBJ_TYPE&&propName.length==2){this[propName[0]]=propName[1]}else{this[propName]=undefined}}return this},strip=function(pattern,str){return isString(str)?str.replace(pattern,EMPTY):str},stripQuotes=function(str){return strip(/\\?\"/g,str)},trim=function(str,len){if(isString(str)){str=strip(/^\s\s*/,str);return typeof len===UNDEF_TYPE?str:str.substring(0,UA_MAX_LENGTH)}};var rgxMapper=function(ua,arrays){if(!ua||!arrays)return;var i=0,j,k,p,q,matches,match;while(i0){if(q.length===2){if(typeof q[1]==FUNC_TYPE){this[q[0]]=q[1].call(this,match)}else{this[q[0]]=q[1]}}else if(q.length===3){if(typeof q[1]===FUNC_TYPE&&!(q[1].exec&&q[1].test)){this[q[0]]=match?q[1].call(this,match,q[2]):undefined}else{this[q[0]]=match?match.replace(q[1],q[2]):undefined}}else if(q.length===4){this[q[0]]=match?q[3].call(this,match.replace(q[1],q[2])):undefined}}else{this[q]=match?match:undefined}}}}i+=2}},strMapper=function(str,map){for(var i in map){if(typeof map[i]===OBJ_TYPE&&map[i].length>0){for(var j=0;j2){this.set(MODEL,"iPad").set(TYPE,TABLET)}break;case UA_OS:if(!this.get(NAME)&&NAVIGATOR_UADATA&&NAVIGATOR_UADATA[PLATFORM]){this.set(NAME,NAVIGATOR_UADATA[PLATFORM])}break;case UA_RESULT:var data=this.data;var detect=function(itemType){return data[itemType].getItem().detectFeature().get()};this.set(UA_BROWSER,detect(UA_BROWSER)).set(UA_CPU,detect(UA_CPU)).set(UA_DEVICE,detect(UA_DEVICE)).set(UA_ENGINE,detect(UA_ENGINE)).set(UA_OS,detect(UA_OS))}}return this};this.parseUA=function(){if(this.itemType!=UA_RESULT){rgxMapper.call(this.data,this.ua,this.rgxMap)}if(this.itemType==UA_BROWSER){this.set(MAJOR,majorize(this.get(VERSION)))}return this};this.parseCH=function(){var uaCH=this.uaCH,rgxMap=this.rgxMap;switch(this.itemType){case UA_BROWSER:case UA_ENGINE:var brands=uaCH[FULLVERLIST]||uaCH[BRANDS],prevName;if(brands){for(var i in brands){var brandName=brands[i].brand||brands[i],brandVersion=brands[i].version;if(this.itemType==UA_BROWSER&&!/not.a.brand/i.test(brandName)&&(!prevName||/chrom/i.test(prevName)&&brandName!=CHROMIUM)){brandName=strMapper(brandName,{Chrome:"Google Chrome",Edge:"Microsoft Edge","Chrome WebView":"Android WebView","Chrome Headless":"HeadlessChrome","Huawei Browser":"HuaweiBrowser","MIUI Browser":"Miui Browser","Opera Mobi":"OperaMobile",Yandex:"YaBrowser"});this.set(NAME,brandName).set(VERSION,brandVersion).set(MAJOR,majorize(brandVersion));prevName=brandName}if(this.itemType==UA_ENGINE&&brandName==CHROMIUM){this.set(VERSION,brandVersion)}}}break;case UA_CPU:var archName=uaCH[ARCHITECTURE];if(archName){if(archName&&uaCH[BITNESS]=="64")archName+="64";rgxMapper.call(this.data,archName+";",rgxMap)}break;case UA_DEVICE:if(uaCH[MOBILE]){this.set(TYPE,MOBILE)}if(uaCH[MODEL]){this.set(MODEL,uaCH[MODEL]);if(!this.get(TYPE)||!this.get(VENDOR)){var reParse={};rgxMapper.call(reParse,"droid 9; "+uaCH[MODEL]+")",rgxMap);if(!this.get(TYPE)&&!!reParse.type){this.set(TYPE,reParse.type)}if(!this.get(VENDOR)&&!!reParse.vendor){this.set(VENDOR,reParse.vendor)}}}if(uaCH[FORMFACTORS]){var ff;if(typeof uaCH[FORMFACTORS]!=="string"){var idx=0;while(!ff&&idx=13?"11":"10";this.set(NAME,osName).set(VERSION,osVersion)}if(this.get(NAME)==WINDOWS&&uaCH[MODEL]=="Xbox"){this.set(NAME,"Xbox").set(VERSION,undefined)}break;case UA_RESULT:var data=this.data;var parse=function(itemType){return data[itemType].getItem().setCH(uaCH).parseCH().get()};this.set(UA_BROWSER,parse(UA_BROWSER)).set(UA_CPU,parse(UA_CPU)).set(UA_DEVICE,parse(UA_DEVICE)).set(UA_ENGINE,parse(UA_ENGINE)).set(UA_OS,parse(UA_OS))}return this};setProps.call(this,[["itemType",itemType],["ua",ua],["uaCH",uaCH],["rgxMap",rgxMap],["data",createIData(this,itemType)]]);return this}function UAParser(ua,extensions,headers){if(typeof ua===OBJ_TYPE){if(isExtensions(ua,true)){if(typeof extensions===OBJ_TYPE){headers=extensions}extensions=ua}else{headers=ua;extensions=undefined}ua=undefined}else if(typeof ua===STR_TYPE&&!isExtensions(extensions,true)){headers=extensions;extensions=undefined}if(headers&&typeof headers.append===FUNC_TYPE){var kv={};headers.forEach(function(v,k){kv[k]=v});headers=kv}if(!(this instanceof UAParser)){return new UAParser(ua,extensions,headers).getResult()}var userAgent=typeof ua===STR_TYPE?ua:headers&&headers[USER_AGENT]?headers[USER_AGENT]:NAVIGATOR&&NAVIGATOR.userAgent?NAVIGATOR.userAgent:EMPTY,httpUACH=new UACHData(headers,true),regexMap=extensions?extend(defaultRegexes,extensions):defaultRegexes,createItemFunc=function(itemType){if(itemType==UA_RESULT){return function(){return new UAItem(itemType,userAgent,regexMap,httpUACH).set("ua",userAgent).set(UA_BROWSER,this.getBrowser()).set(UA_CPU,this.getCPU()).set(UA_DEVICE,this.getDevice()).set(UA_ENGINE,this.getEngine()).set(UA_OS,this.getOS()).get()}}else{return function(){return new UAItem(itemType,userAgent,regexMap[itemType],httpUACH).parseUA().get()}}};setProps.call(this,[["getBrowser",createItemFunc(UA_BROWSER)],["getCPU",createItemFunc(UA_CPU)],["getDevice",createItemFunc(UA_DEVICE)],["getEngine",createItemFunc(UA_ENGINE)],["getOS",createItemFunc(UA_OS)],["getResult",createItemFunc(UA_RESULT)],["getUA",function(){return userAgent}],["setUA",function(ua){if(isString(ua))userAgent=ua.length>UA_MAX_LENGTH?trim(ua,UA_MAX_LENGTH):ua;return this}]]).setUA(userAgent);return this}UAParser.VERSION=LIBVERSION;UAParser.BROWSER=enumerize([NAME,VERSION,MAJOR,TYPE]);UAParser.CPU=enumerize([ARCHITECTURE]);UAParser.DEVICE=enumerize([MODEL,VENDOR,TYPE,CONSOLE,MOBILE,SMARTTV,TABLET,WEARABLE,EMBEDDED]);UAParser.ENGINE=UAParser.OS=enumerize([NAME,VERSION]);export{UAParser}; \ No newline at end of file +var LIBVERSION="2.0.4",UA_MAX_LENGTH=500,USER_AGENT="user-agent",EMPTY="",UNKNOWN="?",FUNC_TYPE="function",UNDEF_TYPE="undefined",OBJ_TYPE="object",STR_TYPE="string",UA_BROWSER="browser",UA_CPU="cpu",UA_DEVICE="device",UA_ENGINE="engine",UA_OS="os",UA_RESULT="result",NAME="name",TYPE="type",VENDOR="vendor",VERSION="version",ARCHITECTURE="architecture",MAJOR="major",MODEL="model",CONSOLE="console",MOBILE="mobile",TABLET="tablet",SMARTTV="smarttv",WEARABLE="wearable",XR="xr",EMBEDDED="embedded",INAPP="inapp",BRANDS="brands",FORMFACTORS="formFactors",FULLVERLIST="fullVersionList",PLATFORM="platform",PLATFORMVER="platformVersion",BITNESS="bitness",CH_HEADER="sec-ch-ua",CH_HEADER_FULL_VER_LIST=CH_HEADER+"-full-version-list",CH_HEADER_ARCH=CH_HEADER+"-arch",CH_HEADER_BITNESS=CH_HEADER+"-"+BITNESS,CH_HEADER_FORM_FACTORS=CH_HEADER+"-form-factors",CH_HEADER_MOBILE=CH_HEADER+"-"+MOBILE,CH_HEADER_MODEL=CH_HEADER+"-"+MODEL,CH_HEADER_PLATFORM=CH_HEADER+"-"+PLATFORM,CH_HEADER_PLATFORM_VER=CH_HEADER_PLATFORM+"-version",CH_ALL_VALUES=[BRANDS,FULLVERLIST,MOBILE,MODEL,PLATFORM,PLATFORMVER,ARCHITECTURE,FORMFACTORS,BITNESS],AMAZON="Amazon",APPLE="Apple",ASUS="ASUS",BLACKBERRY="BlackBerry",GOOGLE="Google",HUAWEI="Huawei",LENOVO="Lenovo",HONOR="Honor",LG="LG",MICROSOFT="Microsoft",MOTOROLA="Motorola",NVIDIA="Nvidia",ONEPLUS="OnePlus",OPPO="OPPO",SAMSUNG="Samsung",SHARP="Sharp",SONY="Sony",XIAOMI="Xiaomi",ZEBRA="Zebra",CHROME="Chrome",CHROMIUM="Chromium",CHROMECAST="Chromecast",EDGE="Edge",FIREFOX="Firefox",OPERA="Opera",FACEBOOK="Facebook",SOGOU="Sogou",PREFIX_MOBILE="Mobile ",SUFFIX_BROWSER=" Browser",WINDOWS="Windows";var isWindow=typeof window!==UNDEF_TYPE,NAVIGATOR=isWindow&&window.navigator?window.navigator:undefined,NAVIGATOR_UADATA=NAVIGATOR&&NAVIGATOR.userAgentData?NAVIGATOR.userAgentData:undefined;var extend=function(defaultRgx,extensions){var mergedRgx={};var extraRgx=extensions;if(!isExtensions(extensions)){extraRgx={};for(var i in extensions){for(var j in extensions[i]){extraRgx[j]=extensions[i][j].concat(extraRgx[j]?extraRgx[j]:[])}}}for(var k in defaultRgx){mergedRgx[k]=extraRgx[k]&&extraRgx[k].length%2===0?extraRgx[k].concat(defaultRgx[k]):defaultRgx[k]}return mergedRgx},enumerize=function(arr){var enums={};for(var i=0;i0){for(var i in str1){if(lowerize(str2)==lowerize(str1[i]))return true}return false}return isString(str1)?lowerize(str2)==lowerize(str1):false},isExtensions=function(obj,deep){for(var prop in obj){return/^(browser|cpu|device|engine|os)$/.test(prop)||(deep?isExtensions(obj[prop]):false)}},isString=function(val){return typeof val===STR_TYPE},itemListToArray=function(header){if(!header)return undefined;var arr=[];var tokens=strip(/\\?\"/g,header).split(",");for(var i=0;i-1){var token=trim(tokens[i]).split(";v=");arr[i]={brand:token[0],version:token[1]}}else{arr[i]=trim(tokens[i])}}return arr},lowerize=function(str){return isString(str)?str.toLowerCase():str},majorize=function(version){return isString(version)?strip(/[^\d\.]/g,version).split(".")[0]:undefined},setProps=function(arr){for(var i in arr){var propName=arr[i];if(typeof propName==OBJ_TYPE&&propName.length==2){this[propName[0]]=propName[1]}else{this[propName]=undefined}}return this},strip=function(pattern,str){return isString(str)?str.replace(pattern,EMPTY):str},stripQuotes=function(str){return strip(/\\?\"/g,str)},trim=function(str,len){if(isString(str)){str=strip(/^\s\s*/,str);return typeof len===UNDEF_TYPE?str:str.substring(0,UA_MAX_LENGTH)}};var rgxMapper=function(ua,arrays){if(!ua||!arrays)return;var i=0,j,k,p,q,matches,match;while(i0){if(q.length===2){if(typeof q[1]==FUNC_TYPE){this[q[0]]=q[1].call(this,match)}else{this[q[0]]=q[1]}}else if(q.length>=3){if(typeof q[1]===FUNC_TYPE&&!(q[1].exec&&q[1].test)){if(q.length>3){this[q[0]]=match?q[1].apply(this,q.slice(2)):undefined}else{this[q[0]]=match?q[1].call(this,match,q[2]):undefined}}else{if(q.length==3){this[q[0]]=match?match.replace(q[1],q[2]):undefined}else if(q.length==4){this[q[0]]=match?q[3].call(this,match.replace(q[1],q[2])):undefined}else if(q.length>4){this[q[0]]=match?q[3].apply(this,[match.replace(q[1],q[2])].concat(q.slice(4))):undefined}}}}else{this[q]=match?match:undefined}}}}i+=2}},strMapper=function(str,map){for(var i in map){if(typeof map[i]===OBJ_TYPE&&map[i].length>0){for(var j=0;j2){this.set(MODEL,"iPad").set(TYPE,TABLET)}break;case UA_OS:if(!this.get(NAME)&&NAVIGATOR_UADATA&&NAVIGATOR_UADATA[PLATFORM]){this.set(NAME,NAVIGATOR_UADATA[PLATFORM])}break;case UA_RESULT:var data=this.data;var detect=function(itemType){return data[itemType].getItem().detectFeature().get()};this.set(UA_BROWSER,detect(UA_BROWSER)).set(UA_CPU,detect(UA_CPU)).set(UA_DEVICE,detect(UA_DEVICE)).set(UA_ENGINE,detect(UA_ENGINE)).set(UA_OS,detect(UA_OS))}}return this};this.parseUA=function(){if(this.itemType!=UA_RESULT){rgxMapper.call(this.data,this.ua,this.rgxMap)}if(this.itemType==UA_BROWSER){this.set(MAJOR,majorize(this.get(VERSION)))}return this};this.parseCH=function(){var uaCH=this.uaCH,rgxMap=this.rgxMap;switch(this.itemType){case UA_BROWSER:case UA_ENGINE:var brands=uaCH[FULLVERLIST]||uaCH[BRANDS],prevName;if(brands){for(var i in brands){var brandName=brands[i].brand||brands[i],brandVersion=brands[i].version;if(this.itemType==UA_BROWSER&&!/not.a.brand/i.test(brandName)&&(!prevName||/Chrom/.test(prevName)&&brandName!=CHROMIUM||prevName==EDGE&&/WebView2/.test(brandName))){brandName=strMapper(brandName,browserHintsMap);prevName=this.get(NAME);if(!(prevName&&!/Chrom/.test(prevName)&&/Chrom/.test(brandName))){this.set(NAME,brandName).set(VERSION,brandVersion).set(MAJOR,majorize(brandVersion))}prevName=brandName}if(this.itemType==UA_ENGINE&&brandName==CHROMIUM){this.set(VERSION,brandVersion)}}}break;case UA_CPU:var archName=uaCH[ARCHITECTURE];if(archName){if(archName&&uaCH[BITNESS]=="64")archName+="64";rgxMapper.call(this.data,archName+";",rgxMap)}break;case UA_DEVICE:if(uaCH[MOBILE]){this.set(TYPE,MOBILE)}if(uaCH[MODEL]){this.set(MODEL,uaCH[MODEL]);if(!this.get(TYPE)||!this.get(VENDOR)){var reParse={};rgxMapper.call(reParse,"droid 9; "+uaCH[MODEL]+")",rgxMap);if(!this.get(TYPE)&&!!reParse.type){this.set(TYPE,reParse.type)}if(!this.get(VENDOR)&&!!reParse.vendor){this.set(VENDOR,reParse.vendor)}}}if(uaCH[FORMFACTORS]){var ff;if(typeof uaCH[FORMFACTORS]!=="string"){var idx=0;while(!ff&&idx=13?"11":"10";this.set(NAME,osName).set(VERSION,osVersion)}if(this.get(NAME)==WINDOWS&&uaCH[MODEL]=="Xbox"){this.set(NAME,"Xbox").set(VERSION,undefined)}break;case UA_RESULT:var data=this.data;var parse=function(itemType){return data[itemType].getItem().setCH(uaCH).parseCH().get()};this.set(UA_BROWSER,parse(UA_BROWSER)).set(UA_CPU,parse(UA_CPU)).set(UA_DEVICE,parse(UA_DEVICE)).set(UA_ENGINE,parse(UA_ENGINE)).set(UA_OS,parse(UA_OS))}return this};setProps.call(this,[["itemType",itemType],["ua",ua],["uaCH",uaCH],["rgxMap",rgxMap],["data",createIData(this,itemType)]]);return this}function UAParser(ua,extensions,headers){if(typeof ua===OBJ_TYPE){if(isExtensions(ua,true)){if(typeof extensions===OBJ_TYPE){headers=extensions}extensions=ua}else{headers=ua;extensions=undefined}ua=undefined}else if(typeof ua===STR_TYPE&&!isExtensions(extensions,true)){headers=extensions;extensions=undefined}if(headers&&typeof headers.append===FUNC_TYPE){var kv={};headers.forEach(function(v,k){kv[k]=v});headers=kv}if(!(this instanceof UAParser)){return new UAParser(ua,extensions,headers).getResult()}var userAgent=typeof ua===STR_TYPE?ua:headers&&headers[USER_AGENT]?headers[USER_AGENT]:NAVIGATOR&&NAVIGATOR.userAgent?NAVIGATOR.userAgent:EMPTY,httpUACH=new UACHData(headers,true),regexMap=extensions?extend(defaultRegexes,extensions):defaultRegexes,createItemFunc=function(itemType){if(itemType==UA_RESULT){return function(){return new UAItem(itemType,userAgent,regexMap,httpUACH).set("ua",userAgent).set(UA_BROWSER,this.getBrowser()).set(UA_CPU,this.getCPU()).set(UA_DEVICE,this.getDevice()).set(UA_ENGINE,this.getEngine()).set(UA_OS,this.getOS()).get()}}else{return function(){return new UAItem(itemType,userAgent,regexMap[itemType],httpUACH).parseUA().get()}}};setProps.call(this,[["getBrowser",createItemFunc(UA_BROWSER)],["getCPU",createItemFunc(UA_CPU)],["getDevice",createItemFunc(UA_DEVICE)],["getEngine",createItemFunc(UA_ENGINE)],["getOS",createItemFunc(UA_OS)],["getResult",createItemFunc(UA_RESULT)],["getUA",function(){return userAgent}],["setUA",function(ua){if(isString(ua))userAgent=ua.length>UA_MAX_LENGTH?trim(ua,UA_MAX_LENGTH):ua;return this}]]).setUA(userAgent);return this}UAParser.VERSION=LIBVERSION;UAParser.BROWSER=enumerize([NAME,VERSION,MAJOR,TYPE]);UAParser.CPU=enumerize([ARCHITECTURE]);UAParser.DEVICE=enumerize([MODEL,VENDOR,TYPE,CONSOLE,MOBILE,SMARTTV,TABLET,WEARABLE,EMBEDDED]);UAParser.ENGINE=UAParser.OS=enumerize([NAME,VERSION]);export{UAParser}; \ No newline at end of file diff --git a/dist/ua-parser.pack.js b/dist/ua-parser.pack.js index 044d816..d6d094f 100644 --- a/dist/ua-parser.pack.js +++ b/dist/ua-parser.pack.js @@ -1,4 +1,4 @@ -/* UAParser.js v2.0.3 +/* UAParser.js v2.0.4 Copyright © 2012-2025 Faisal Salman UAParser.js PRO Enterprise License */ -((i,l)=>{function U(i){for(var e={},t=0;t{var t,o={},r=e;if(!_i(e))for(var a in r={},e)for(var s in e[a])r[s]=e[a][s].concat(r[s]||[]);for(t in i)o[t]=r[t]&&r[t].length%2==0?r[t].concat(i[t]):i[t];return o})(Ii,e):Ii,j.call(this,[["getBrowser",(n=function(i){return i==g?function(){return new Bi(i,r,s,a).set("ua",r).set(u,this.getBrowser()).set(h,this.getCPU()).set(p,this.getDevice()).set(m,this.getEngine()).set(f,this.getOS()).get()}:function(){return new Bi(i,r,s[i],a).parseUA().get()}})(u)],["getCPU",n(h)],["getDevice",n(p)],["getEngine",n(m)],["getOS",n(f)],["getResult",n(g)],["getUA",function(){return r}],["setUA",function(i){return H(i)&&(r=i.length>E?Hi(i,E):i),this}]]).setUA(r),this):new I(i,e,t).getResult()}I.VERSION="2.0.3",I.BROWSER=U([v,y,L,k]),I.CPU=U([C]),I.DEVICE=U([T,x,k,G,S,e,r,t,D]),I.ENGINE=I.OS=U([v,y]),typeof exports!==n?(exports=typeof module!==n&&module.exports?module.exports=I:exports).UAParser=I:typeof define===R&&define.amd?define(function(){return I}):Ti&&(i.UAParser=I);var Ri,Vi=Ti&&(i.jQuery||i.Zepto);Vi&&!Vi.ua&&(Ri=new I,Vi.ua=Ri.getResult(),Vi.ua.get=function(){return Ri.getUA()},Vi.ua.set=function(i){Ri.setUA(i);var e,t=Ri.getResult();for(e in t)Vi.ua[e]=t[e]})})("object"==typeof window?window:this); \ No newline at end of file +((i,l)=>{function I(i){for(var e={},t=0;t{var t,o={},r=e;if(!Ti(e))for(var a in r={},e)for(var s in e[a])r[s]=e[a][s].concat(r[s]||[]);for(t in i)o[t]=r[t]&&r[t].length%2==0?r[t].concat(i[t]):i[t];return o})(Pi,e):Pi,M.call(this,[["getBrowser",(n=function(i){return i==g?function(){return new Gi(i,r,s,a).set("ua",r).set(u,this.getBrowser()).set(h,this.getCPU()).set(p,this.getDevice()).set(m,this.getEngine()).set(f,this.getOS()).get()}:function(){return new Gi(i,r,s[i],a).parseUA().get()}})(u)],["getCPU",n(h)],["getDevice",n(p)],["getEngine",n(m)],["getOS",n(f)],["getResult",n(g)],["getUA",function(){return r}],["setUA",function(i){return O(i)&&(r=i.length>U?Mi(i,U):i),this}]]).setUA(r),this):new V(i,e,t).getResult()}V.VERSION="2.0.4",V.BROWSER=I([v,y,G,k]),V.CPU=I([C]),V.DEVICE=I([S,x,k,W,_,e,r,t,F]),V.ENGINE=V.OS=I([v,y]),typeof exports!==n?(exports=typeof module!==n&&module.exports?module.exports=V:exports).UAParser=V:typeof define===R&&define.amd?define(function(){return V}):qi&&(i.UAParser=V);var Wi,Ni=qi&&(i.jQuery||i.Zepto);Ni&&!Ni.ua&&(Wi=new V,Ni.ua=Wi.getResult(),Ni.ua.get=function(){return Wi.getUA()},Ni.ua.set=function(i){Wi.setUA(i);var e,t=Wi.getResult();for(e in t)Ni.ua[e]=t[e]})})("object"==typeof window?window:this); \ No newline at end of file diff --git a/dist/ua-parser.pack.mjs b/dist/ua-parser.pack.mjs index 2bd4ce8..197a63d 100644 --- a/dist/ua-parser.pack.mjs +++ b/dist/ua-parser.pack.mjs @@ -1,4 +1,4 @@ -/* UAParser.js v2.0.3 +/* UAParser.js v2.0.4 Copyright © 2012-2025 Faisal Salman UAParser.js PRO Enterprise License */ -function E(i){for(var e={},o=0;o{var o,t={},r=e;if(!_i(e))for(var a in r={},e)for(var s in e[a])r[s]=e[a][s].concat(r[s]||[]);for(o in i)t[o]=r[o]&&r[o].length%2==0?r[o].concat(i[o]):i[o];return t})(Ii,e):Ii,M.call(this,[["getBrowser",(n=function(i){return i==f?function(){return new Pi(i,r,s,a).set("ua",r).set(c,this.getBrowser()).set(u,this.getCPU()).set(h,this.getDevice()).set(p,this.getEngine()).set(m,this.getOS()).get()}:function(){return new Pi(i,r,s[i],a).parseUA().get()}})(c)],["getCPU",n(u)],["getDevice",n(h)],["getEngine",n(p)],["getOS",n(m)],["getResult",n(f)],["getUA",function(){return r}],["setUA",function(i){return A(i)&&(r=i.length>B?Ai(i,B):i),this}]]).setUA(r),this):new j(i,e,o).getResult()}j.VERSION="2.0.3",j.BROWSER=E([g,x,C,v]),j.CPU=E([y]),j.DEVICE=E([T,k,v,L,S,i,r,e,F]),j.ENGINE=j.OS=E([g,x]);export{j as UAParser}; \ No newline at end of file +function I(i){for(var e={},o=0;o{var o,t={},r=e;if(!zi(e))for(var a in r={},e)for(var s in e[a])r[s]=e[a][s].concat(r[s]||[]);for(o in i)t[o]=r[o]&&r[o].length%2==0?r[o].concat(i[o]):i[o];return t})(Ii,e):Ii,A.call(this,[["getBrowser",(n=function(i){return i==f?function(){return new Li(i,r,s,a).set("ua",r).set(c,this.getBrowser()).set(u,this.getCPU()).set(h,this.getDevice()).set(p,this.getEngine()).set(m,this.getOS()).get()}:function(){return new Li(i,r,s[i],a).parseUA().get()}})(c)],["getCPU",n(u)],["getDevice",n(h)],["getEngine",n(p)],["getOS",n(m)],["getResult",n(f)],["getUA",function(){return r}],["setUA",function(i){return H(i)&&(r=i.length>B?Mi(i,B):i),this}]]).setUA(r),this):new V(i,e,o).getResult()}V.VERSION="2.0.4",V.BROWSER=I([g,x,C,v]),V.CPU=I([y]),V.DEVICE=I([S,k,v,G,_,i,r,e,N]),V.ENGINE=V.OS=I([g,x]);export{V as UAParser}; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 0330980..1565791 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@ua-parser-js/pro-enterprise", - "version": "2.0.3", + "version": "2.0.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@ua-parser-js/pro-enterprise", - "version": "2.0.3", + "version": "2.0.4", "funding": [ { "type": "opencollective", diff --git a/package.json b/package.json index 207e4ab..521ba47 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "title": "UAParser.js PRO Enterprise", "name": "@ua-parser-js/pro-enterprise", - "version": "2.0.3", + "version": "2.0.4", "author": "Faisal Salman (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": [ diff --git a/src/enums/ua-parser-enums.d.ts b/src/enums/ua-parser-enums.d.ts index 2fb0db5..e8d3615 100644 --- a/src/enums/ua-parser-enums.d.ts +++ b/src/enums/ua-parser-enums.d.ts @@ -1,4 +1,4 @@ -// Type definitions for Enums submodule of UAParser.js v2.0.3 +// Type definitions for Enums submodule of UAParser.js v2.0.4 // Project: https://github.com/faisalman/ua-parser-js // Definitions by: Faisal Salman @@ -16,7 +16,6 @@ export const Browser: Readonly<{ BAIDU: "Baidu Browser"; BASILISK: "Basilisk"; BLAZER: "Blazer"; - BLU: "BLU"; BOLT: "Bolt"; BOWSER: "Bowser"; BRAVE: "Brave"; @@ -39,6 +38,8 @@ export const Browser: Readonly<{ DUCKDUCKGO: "DuckDuckGo"; ECOSIA: "Ecosia"; EDGE: "Edge"; + EDGE_WEBVIEW: "Edge WebView"; + EDGE_WEBVIEW2: "Edge WebView2"; EPIPHANY: "Epiphany"; FACEBOOK: "Facebook"; FALKON: "Falkon"; @@ -203,6 +204,7 @@ export const Vendor: Readonly<{ ATT: "AT&T"; BENQ: "BenQ"; BLACKBERRY: "BlackBerry"; + BLU: "BLU"; CAT: "Cat"; DELL: "Dell"; ENERGIZER: "Energizer"; @@ -221,6 +223,7 @@ export const Vendor: Readonly<{ ITEL: "itel"; JOLLA: "Jolla"; KOBO: "Kobo"; + LAVA: "Lava"; LENOVO: "Lenovo"; LG: "LG"; MEIZU: "Meizu"; @@ -241,6 +244,7 @@ export const Vendor: Readonly<{ PICO: "Pico"; POLYTRON: "Polytron"; REALME: "Realme"; + RETROID: "Retroid"; RIM: "RIM"; ROKU: "Roku"; SAMSUNG: "Samsung"; @@ -255,6 +259,7 @@ export const Vendor: Readonly<{ TESLA: "Tesla"; ULEFONE: "Ulefone"; VIVO: "Vivo"; + VIZIO: "Vizio"; VODAFONE: "Vodafone"; XBOX: "Xbox"; XIAOMI: "Xiaomi"; @@ -288,6 +293,7 @@ export const OS: Readonly<{ AMIGA_OS: "Amiga OS"; ANDROID: "Android"; ANDROID_X86: "Android-x86"; + ARCAOS: "ArcaOS"; ARCH: "Arch"; BADA: "Bada"; BEOS: "BeOS"; @@ -318,6 +324,7 @@ export const OS: Readonly<{ IOS: "iOS"; JOLI: "Joli"; KAIOS: "KaiOS"; + KNOPPIX: "Knoppix"; KUBUNTU: "Kubuntu"; LINPUS: "Linpus"; LINSPIRE: "Linspire"; @@ -366,9 +373,12 @@ export const OS: Readonly<{ WATCHOS: "watchOS"; WEBOS: "WebOS"; WINDOWS: "Windows"; + WINDOWS_CE: "Windows CE"; WINDOWS_IOT: "Windows IoT"; WINDOWS_MOBILE: "Windows Mobile"; WINDOWS_PHONE: "Windows Phone"; + WINDOWS_RT: "Windows RT"; XBOX: "Xbox"; + XUBUNTU: "Xubuntu"; ZENWALK: "Zenwalk"; }>; diff --git a/src/enums/ua-parser-enums.js b/src/enums/ua-parser-enums.js index a18b79d..d106bdc 100644 --- a/src/enums/ua-parser-enums.js +++ b/src/enums/ua-parser-enums.js @@ -1,5 +1,5 @@ /////////////////////////////////////////////// -/* Enums for UAParser.js v2.0.3 +/* Enums for UAParser.js v2.0.4 https://github.com/faisalman/ua-parser-js Author: Faisal Salman UAParser.js PRO Enterprise License */ @@ -21,7 +21,6 @@ const Browser = Object.freeze({ BAIDU: 'Baidu Browser', BASILISK: 'Basilisk', BLAZER: 'Blazer', - BLU: 'BLU', BOLT: 'Bolt', BOWSER: 'Bowser', BRAVE: 'Brave', @@ -44,6 +43,8 @@ const Browser = Object.freeze({ DUCKDUCKGO: 'DuckDuckGo', ECOSIA: 'Ecosia', EDGE: 'Edge', + EDGE_WEBVIEW: 'Edge WebView', + EDGE_WEBVIEW2: 'Edge WebView2', EPIPHANY: 'Epiphany', FACEBOOK: 'Facebook', FALKON: 'Falkon', @@ -214,6 +215,7 @@ const Vendor = Object.freeze({ ATT: 'AT&T', BENQ: 'BenQ', BLACKBERRY: 'BlackBerry', + BLU: 'BLU', CAT: 'Cat', DELL: 'Dell', ENERGIZER: 'Energizer', @@ -232,6 +234,7 @@ const Vendor = Object.freeze({ ITEL: 'itel', JOLLA: 'Jolla', KOBO: 'Kobo', + LAVA: 'Lava', LENOVO: 'Lenovo', LG: 'LG', MEIZU: 'Meizu', @@ -252,6 +255,7 @@ const Vendor = Object.freeze({ PICO: 'Pico', POLYTRON: 'Polytron', REALME: 'Realme', + RETROID: 'Retroid', RIM: 'RIM', ROKU: 'Roku', SAMSUNG: 'Samsung', @@ -266,6 +270,7 @@ const Vendor = Object.freeze({ TESLA: 'Tesla', ULEFONE: 'Ulefone', VIVO: 'Vivo', + VIZIO: 'Vizio', VODAFONE: 'Vodafone', XBOX: 'Xbox', XIAOMI: 'Xiaomi', @@ -303,6 +308,7 @@ const OS = Object.freeze({ AMIGA_OS: 'Amiga OS', ANDROID: 'Android', ANDROID_X86: 'Android-x86', + ARCAOS: 'ArcaOS', ARCH: 'Arch', BADA: 'Bada', BEOS: 'BeOS', @@ -333,6 +339,7 @@ const OS = Object.freeze({ IOS: 'iOS', JOLI: 'Joli', KAIOS: 'KaiOS', + KNOPPIX: 'Knoppix', KUBUNTU: 'Kubuntu', LINPUS: 'Linpus', LINSPIRE: 'Linspire', @@ -381,10 +388,13 @@ const OS = Object.freeze({ WATCHOS: 'watchOS', WEBOS: 'WebOS', WINDOWS: 'Windows', + WINDOWS_CE: 'Windows CE', WINDOWS_IOT: 'Windows IoT', WINDOWS_MOBILE: 'Windows Mobile', WINDOWS_PHONE: 'Windows Phone', + WINDOWS_RT: 'Windows RT', XBOX: 'Xbox', + XUBUNTU: 'Xubuntu', ZENWALK: 'Zenwalk' // TODO : test! diff --git a/src/enums/ua-parser-enums.mjs b/src/enums/ua-parser-enums.mjs index 46d40f8..91f1157 100644 --- a/src/enums/ua-parser-enums.mjs +++ b/src/enums/ua-parser-enums.mjs @@ -3,7 +3,7 @@ // Source: /src/enums/ua-parser-enums.js /////////////////////////////////////////////// -/* Enums for UAParser.js v2.0.3 +/* Enums for UAParser.js v2.0.4 https://github.com/faisalman/ua-parser-js Author: Faisal Salman UAParser.js PRO Enterprise License */ @@ -25,7 +25,6 @@ const Browser = Object.freeze({ BAIDU: 'Baidu Browser', BASILISK: 'Basilisk', BLAZER: 'Blazer', - BLU: 'BLU', BOLT: 'Bolt', BOWSER: 'Bowser', BRAVE: 'Brave', @@ -48,6 +47,8 @@ const Browser = Object.freeze({ DUCKDUCKGO: 'DuckDuckGo', ECOSIA: 'Ecosia', EDGE: 'Edge', + EDGE_WEBVIEW: 'Edge WebView', + EDGE_WEBVIEW2: 'Edge WebView2', EPIPHANY: 'Epiphany', FACEBOOK: 'Facebook', FALKON: 'Falkon', @@ -218,6 +219,7 @@ const Vendor = Object.freeze({ ATT: 'AT&T', BENQ: 'BenQ', BLACKBERRY: 'BlackBerry', + BLU: 'BLU', CAT: 'Cat', DELL: 'Dell', ENERGIZER: 'Energizer', @@ -236,6 +238,7 @@ const Vendor = Object.freeze({ ITEL: 'itel', JOLLA: 'Jolla', KOBO: 'Kobo', + LAVA: 'Lava', LENOVO: 'Lenovo', LG: 'LG', MEIZU: 'Meizu', @@ -256,6 +259,7 @@ const Vendor = Object.freeze({ PICO: 'Pico', POLYTRON: 'Polytron', REALME: 'Realme', + RETROID: 'Retroid', RIM: 'RIM', ROKU: 'Roku', SAMSUNG: 'Samsung', @@ -270,6 +274,7 @@ const Vendor = Object.freeze({ TESLA: 'Tesla', ULEFONE: 'Ulefone', VIVO: 'Vivo', + VIZIO: 'Vizio', VODAFONE: 'Vodafone', XBOX: 'Xbox', XIAOMI: 'Xiaomi', @@ -307,6 +312,7 @@ const OS = Object.freeze({ AMIGA_OS: 'Amiga OS', ANDROID: 'Android', ANDROID_X86: 'Android-x86', + ARCAOS: 'ArcaOS', ARCH: 'Arch', BADA: 'Bada', BEOS: 'BeOS', @@ -337,6 +343,7 @@ const OS = Object.freeze({ IOS: 'iOS', JOLI: 'Joli', KAIOS: 'KaiOS', + KNOPPIX: 'Knoppix', KUBUNTU: 'Kubuntu', LINPUS: 'Linpus', LINSPIRE: 'Linspire', @@ -385,10 +392,13 @@ const OS = Object.freeze({ WATCHOS: 'watchOS', WEBOS: 'WebOS', WINDOWS: 'Windows', + WINDOWS_CE: 'Windows CE', WINDOWS_IOT: 'Windows IoT', WINDOWS_MOBILE: 'Windows Mobile', WINDOWS_PHONE: 'Windows Phone', + WINDOWS_RT: 'Windows RT', XBOX: 'Xbox', + XUBUNTU: 'Xubuntu', ZENWALK: 'Zenwalk' // TODO : test! diff --git a/src/extensions/ua-parser-extensions.d.ts b/src/extensions/ua-parser-extensions.d.ts index 3b9b63a..4ee31dd 100644 --- a/src/extensions/ua-parser-extensions.d.ts +++ b/src/extensions/ua-parser-extensions.d.ts @@ -1,4 +1,4 @@ -// Type definitions for Helpers submodule of UAParser.js v2.0.3 +// Type definitions for Helpers submodule of UAParser.js v2.0.4 // Project: https://github.com/faisalman/ua-parser-js // Definitions by: Faisal Salman diff --git a/src/extensions/ua-parser-extensions.js b/src/extensions/ua-parser-extensions.js index 98a8ae6..b09195a 100644 --- a/src/extensions/ua-parser-extensions.js +++ b/src/extensions/ua-parser-extensions.js @@ -1,5 +1,5 @@ /////////////////////////////////////////////// -/* Extensions for UAParser.js v2.0.3 +/* Extensions for UAParser.js v2.0.4 https://github.com/faisalman/ua-parser-js Author: Faisal Salman UAParser.js PRO Enterprise License */ @@ -48,13 +48,15 @@ const Crawlers = Object.freeze({ // DuckDuckBot - http://duckduckgo.com/duckduckbot.html // FacebookBot - https://developers.facebook.com/docs/sharing/bot/ // GPTBot - https://platform.openai.com/docs/gptbot + // iAskBot - https://iask.ai // LinkedInBot - http://www.linkedin.com // MJ12bot - https://mj12bot.com/ // MojeekBot - https://www.mojeek.com/bot.html + // Onespot - https://www.onespot.com/identifying-traffic.html // OpenAI's SearchGPT - https://platform.openai.com/docs/bots // PerplexityBot - https://perplexity.ai/perplexitybot // SeznamBot - http://napoveda.seznam.cz/seznambot-intro - /((?:adidx|ahrefs|amazon|bing|cc|dot|duckduck|exa|facebook|gpt|linkedin|mj12|mojeek|oai-search|perplexity|semrush|seznam)bot)\/([\w\.-]+)/i, + /((?:adidx|ahrefs|amazon|bing|cc|dot|duckduck|exa|facebook|gpt|iask|linkedin|mj12|mojeek|oai-search|onespot-scraper|perplexity|semrush|seznam)bot)\/([\w\.-]+)/i, // Applebot - http://apple.com/go/applebot /(applebot(?:-extended)?)\/?([\w\.]*)/i, @@ -68,6 +70,9 @@ const Crawlers = Object.freeze({ // Coc Coc Bot - https://help.coccoc.com/en/search-engine /(coccocbot-(?:image|web))\/([\w\.]+)/i, + // Daum + /(daum(?:oa)?(?:-image)?)[ \/]([\w\.]+)/i, + // Facebook / Meta // https://developers.facebook.com/docs/sharing/webmasters/web-crawlers /(facebook(?:externalhit|catalog)|meta-externalagent)\/([\w\.]+)/i, @@ -78,6 +83,9 @@ const Crawlers = Object.freeze({ // Internet Archive (archive.org) /(ia_archiver|archive\.org_bot)\/?([\w\.]*)/i, + // Qwantbot - https://help.qwant.com/bot + /(qwantbot)[-\w]*\/?([\w\.]*)/i, + // SemrushBot - http://www.semrush.com/bot.html /((?:semrush|splitsignal)bot[-abcfimostw]*)\/?([\w\.-]*)/i, @@ -93,8 +101,8 @@ const Crawlers = Object.freeze({ // Yeti (Naver) /(yeti)\/([\w\.]+)/i, - // aiHitBot / Diffbot / Linespider / Magpie-Crawler / Omgilibot / OpenAI Image Downloader / Webzio-Extended / Screaming Frog SEO Spider / Timpibot / VelenPublicWebCrawler / YisouSpider / YouBot - /((?:aihit|diff|timpi|you)bot|omgili(?:bot)?|openai image downloader|(?:magpie-|velenpublicweb)crawler|webzio-extended|(?:screaming frog seo |line|yisou)spider)\/?([\w\.]*)/i + // aiHitBot / Diffbot / Linespider / Magpie-Crawler / Omgilibot / OpenAI Image Downloader / Webzio-Extended / Screaming Frog SEO Spider / Startpage / Timpibot / VelenPublicWebCrawler / YisouSpider / YouBot + /((?:aihit|diff|timpi|you)bot|omgili(?:bot)?|openai image downloader|(?:magpie-|velenpublicweb)crawler|startpageprivateimageproxy|webzio-extended|(?:chatglm-|line|screaming frog seo |yisou)spider)\/?([\w\.]*)/i ], [NAME, VERSION, [TYPE, CRAWLER]], @@ -204,9 +212,18 @@ const ExtraDevices = Object.freeze({ const Emails = Object.freeze({ browser : [ [ - // Evolution / Kontact/KMail / [Microsoft/Mac] Outlook / Thunderbird - /(airmail|bluemail|emclient|evolution|foxmail|kmail2?|kontact|(?:microsoft |mac)?outlook(?:-express)?|navermailapp|(?!chrom.+)sparrow|thunderbird|yahoo)(?:m.+ail; |[\/ ])([\w\.]+)/i - ], [NAME, VERSION, [TYPE, EMAIL]] + // Evolution / Kontact/KMail[2] / [Microsoft/Mac] Outlook / Thunderbird + // Airmail / BlueMail / DaumMail / eMClient / Foxmail / NaverMailApp / Polymail + // ProtonMail / SparkDesktop / Sparrow / Yahoo! Mail / Zimbra / ZohoMail-Desktop + /((?:air|blue|daum|fox|poly|proton)mail|emclient|evolution|kmail2?|kontact|(?:microsoft |mac)?outlook(?:-express)?|navermailapp|(?!chrom.+)sparrow|sparkdesktop|thunderbird|yahoo|zohomail-desktop)(?:m.+ail; |[\/ ])([\w\.]+)/i, + + // Apple's Mail + /(mail)\/([\w\.]+) cf/i + ], [NAME, VERSION, [TYPE, EMAIL]], [ + + // Zimbra + /zdesktop\/([\w\.]+)/i + ], [VERSION, [NAME, 'Zimbra'], [TYPE, EMAIL]] ] }); @@ -222,8 +239,11 @@ const Fetchers = Object.freeze({ // DuckAssistBot - https://duckduckgo.com/duckassistbot/ // Better Uptime / BingPreview / Mastodon / MicrosoftPreview / Pinterestbot / Redditbot / Rogerbot / SiteAuditBot / Telegrambot / Twitterbot / UptimeRobot // Google Site Verifier / Meta / Yahoo! Japan + // Iframely - https://iframely.com/docs/about + // Perplexity-User - https://docs.perplexity.ai/guides/bots + // MistralAI-User - https://docs.mistral.ai/robots/ // Yandex Bots - https://yandex.com/bots - /(ahrefssiteaudit|(?:bing|microsoft)preview|chatgpt-user|mastodon|(?:discord|duckassist|linkedin|pinterest|reddit|roger|siteaudit|twitter|uptimero)bot|google-site-verification|meta-externalfetcher|y!?j-dlc|yandex(?:calendar|direct(?:dyn)?|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) cardyb\/([\w\.]+)/i, @@ -257,13 +277,31 @@ const Fetchers = Object.freeze({ /////////////////// const InApps = Object.freeze({ - browser : [ + browser : [[ + // Discord/Figma/Flipboard/Mattermost/Notion/Postman/Rambox/Rocket.Chat/Slack/Teams + /\b(discord|figma|mattermost|notion|postman|rambox|rocket.chat|slack|teams)\/([\w\.]+).+(electron\/|; ios)/i, + /(flipboard)\/([\w\.]+)/i + ], [NAME, VERSION, [TYPE, INAPP]], [ + + // Evernote/Teams on mobile + /(evernote) win/i, + /(teams)mobile-(ios|and)/i + ], [NAME, [TYPE, INAPP]], [ + // Slack - [/(?:slack(?=.+electron|.+ios)|chatlyio)\/([\d\.]+)/i], - [VERSION, [NAME, 'Slack'], [TYPE, INAPP]], + /chatlyio\/([\d\.]+)/i], + [VERSION, [NAME, 'Slack'], [TYPE, INAPP]], [ + + // TikTok Lite + /ultralite app_version\/([\w\.]+)/i], + [VERSION, [NAME, 'TikTok Lite'], [TYPE, INAPP]], [ + + // VS Code + /\) code\/([\d\.]+).+electron\//i], + [VERSION, [NAME, 'VS Code'], [TYPE, INAPP]], [ // Yahoo! Japan - [/jp\.co\.yahoo\.(?:android\.yjtop|ipn\.appli)\/([\d\.]+)/i], + /jp\.co\.yahoo\.(?:android\.yjtop|ipn\.appli)\/([\d\.]+)/i], [VERSION, [NAME, 'Yahoo! Japan'], [TYPE, INAPP]] ] }); @@ -328,8 +366,10 @@ const Libraries = Object.freeze({ browser : [ // Apache-HttpClient/Axios/go-http-client/got/GuzzleHttp/Java[-HttpClient]/jsdom/libwww-perl/lua-resty-http/Needle/node-fetch/OkHttp/PHP-SOAP/PostmanRuntime/python-urllib/python-requests/Scrapy/superagent [ - /^(apache-httpclient|axios|(?:go|java)-http-client|got|guzzlehttp|java|libwww-perl|lua-resty-http|needle|node-(?:fetch|superagent)|okhttp|php-soap|postmanruntime|python-(?:urllib|requests)|scrapy)\/([\w\.]+)/i, - /(jsdom|(?<=\()java)\/([\w\.]+)/i + /^(apache-httpclient|axios|(?:go|java)-http-client|got|guzzlehttp|java|libwww-perl|lua-resty-http|needle|node-(?:fetch|superagent)|okhttp|php-soap|postmanruntime|python-(?:httpx|urllib[23]?|requests)|scrapy)\/([\w\.]+)/i, + /(adobeair|aiohttp|jsdom)\/([\w\.]+)/i, + /(nutch)-([\w\.-]+)(\(|$)/i, + /\((java)\/([\w\.]+)/i ], [NAME, VERSION, [TYPE, LIBRARY]] ] }); diff --git a/src/extensions/ua-parser-extensions.mjs b/src/extensions/ua-parser-extensions.mjs index 5884073..8bc7ed7 100644 --- a/src/extensions/ua-parser-extensions.mjs +++ b/src/extensions/ua-parser-extensions.mjs @@ -3,7 +3,7 @@ // Source: /src/extensions/ua-parser-extensions.js /////////////////////////////////////////////// -/* Extensions for UAParser.js v2.0.3 +/* Extensions for UAParser.js v2.0.4 https://github.com/faisalman/ua-parser-js Author: Faisal Salman UAParser.js PRO Enterprise License */ @@ -52,13 +52,15 @@ const Crawlers = Object.freeze({ // DuckDuckBot - http://duckduckgo.com/duckduckbot.html // FacebookBot - https://developers.facebook.com/docs/sharing/bot/ // GPTBot - https://platform.openai.com/docs/gptbot + // iAskBot - https://iask.ai // LinkedInBot - http://www.linkedin.com // MJ12bot - https://mj12bot.com/ // MojeekBot - https://www.mojeek.com/bot.html + // Onespot - https://www.onespot.com/identifying-traffic.html // OpenAI's SearchGPT - https://platform.openai.com/docs/bots // PerplexityBot - https://perplexity.ai/perplexitybot // SeznamBot - http://napoveda.seznam.cz/seznambot-intro - /((?:adidx|ahrefs|amazon|bing|cc|dot|duckduck|exa|facebook|gpt|linkedin|mj12|mojeek|oai-search|perplexity|semrush|seznam)bot)\/([\w\.-]+)/i, + /((?:adidx|ahrefs|amazon|bing|cc|dot|duckduck|exa|facebook|gpt|iask|linkedin|mj12|mojeek|oai-search|onespot-scraper|perplexity|semrush|seznam)bot)\/([\w\.-]+)/i, // Applebot - http://apple.com/go/applebot /(applebot(?:-extended)?)\/?([\w\.]*)/i, @@ -72,6 +74,9 @@ const Crawlers = Object.freeze({ // Coc Coc Bot - https://help.coccoc.com/en/search-engine /(coccocbot-(?:image|web))\/([\w\.]+)/i, + // Daum + /(daum(?:oa)?(?:-image)?)[ \/]([\w\.]+)/i, + // Facebook / Meta // https://developers.facebook.com/docs/sharing/webmasters/web-crawlers /(facebook(?:externalhit|catalog)|meta-externalagent)\/([\w\.]+)/i, @@ -82,6 +87,9 @@ const Crawlers = Object.freeze({ // Internet Archive (archive.org) /(ia_archiver|archive\.org_bot)\/?([\w\.]*)/i, + // Qwantbot - https://help.qwant.com/bot + /(qwantbot)[-\w]*\/?([\w\.]*)/i, + // SemrushBot - http://www.semrush.com/bot.html /((?:semrush|splitsignal)bot[-abcfimostw]*)\/?([\w\.-]*)/i, @@ -97,8 +105,8 @@ const Crawlers = Object.freeze({ // Yeti (Naver) /(yeti)\/([\w\.]+)/i, - // aiHitBot / Diffbot / Linespider / Magpie-Crawler / Omgilibot / OpenAI Image Downloader / Webzio-Extended / Screaming Frog SEO Spider / Timpibot / VelenPublicWebCrawler / YisouSpider / YouBot - /((?:aihit|diff|timpi|you)bot|omgili(?:bot)?|openai image downloader|(?:magpie-|velenpublicweb)crawler|webzio-extended|(?:screaming frog seo |line|yisou)spider)\/?([\w\.]*)/i + // aiHitBot / Diffbot / Linespider / Magpie-Crawler / Omgilibot / OpenAI Image Downloader / Webzio-Extended / Screaming Frog SEO Spider / Startpage / Timpibot / VelenPublicWebCrawler / YisouSpider / YouBot + /((?:aihit|diff|timpi|you)bot|omgili(?:bot)?|openai image downloader|(?:magpie-|velenpublicweb)crawler|startpageprivateimageproxy|webzio-extended|(?:chatglm-|line|screaming frog seo |yisou)spider)\/?([\w\.]*)/i ], [NAME, VERSION, [TYPE, CRAWLER]], @@ -208,9 +216,18 @@ const ExtraDevices = Object.freeze({ const Emails = Object.freeze({ browser : [ [ - // Evolution / Kontact/KMail / [Microsoft/Mac] Outlook / Thunderbird - /(airmail|bluemail|emclient|evolution|foxmail|kmail2?|kontact|(?:microsoft |mac)?outlook(?:-express)?|navermailapp|(?!chrom.+)sparrow|thunderbird|yahoo)(?:m.+ail; |[\/ ])([\w\.]+)/i - ], [NAME, VERSION, [TYPE, EMAIL]] + // Evolution / Kontact/KMail[2] / [Microsoft/Mac] Outlook / Thunderbird + // Airmail / BlueMail / DaumMail / eMClient / Foxmail / NaverMailApp / Polymail + // ProtonMail / SparkDesktop / Sparrow / Yahoo! Mail / Zimbra / ZohoMail-Desktop + /((?:air|blue|daum|fox|poly|proton)mail|emclient|evolution|kmail2?|kontact|(?:microsoft |mac)?outlook(?:-express)?|navermailapp|(?!chrom.+)sparrow|sparkdesktop|thunderbird|yahoo|zohomail-desktop)(?:m.+ail; |[\/ ])([\w\.]+)/i, + + // Apple's Mail + /(mail)\/([\w\.]+) cf/i + ], [NAME, VERSION, [TYPE, EMAIL]], [ + + // Zimbra + /zdesktop\/([\w\.]+)/i + ], [VERSION, [NAME, 'Zimbra'], [TYPE, EMAIL]] ] }); @@ -226,8 +243,11 @@ const Fetchers = Object.freeze({ // DuckAssistBot - https://duckduckgo.com/duckassistbot/ // Better Uptime / BingPreview / Mastodon / MicrosoftPreview / Pinterestbot / Redditbot / Rogerbot / SiteAuditBot / Telegrambot / Twitterbot / UptimeRobot // Google Site Verifier / Meta / Yahoo! Japan + // Iframely - https://iframely.com/docs/about + // Perplexity-User - https://docs.perplexity.ai/guides/bots + // MistralAI-User - https://docs.mistral.ai/robots/ // Yandex Bots - https://yandex.com/bots - /(ahrefssiteaudit|(?:bing|microsoft)preview|chatgpt-user|mastodon|(?:discord|duckassist|linkedin|pinterest|reddit|roger|siteaudit|twitter|uptimero)bot|google-site-verification|meta-externalfetcher|y!?j-dlc|yandex(?:calendar|direct(?:dyn)?|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) cardyb\/([\w\.]+)/i, @@ -261,13 +281,31 @@ const Fetchers = Object.freeze({ /////////////////// const InApps = Object.freeze({ - browser : [ + browser : [[ + // Discord/Figma/Flipboard/Mattermost/Notion/Postman/Rambox/Rocket.Chat/Slack/Teams + /\b(discord|figma|mattermost|notion|postman|rambox|rocket.chat|slack|teams)\/([\w\.]+).+(electron\/|; ios)/i, + /(flipboard)\/([\w\.]+)/i + ], [NAME, VERSION, [TYPE, INAPP]], [ + + // Evernote/Teams on mobile + /(evernote) win/i, + /(teams)mobile-(ios|and)/i + ], [NAME, [TYPE, INAPP]], [ + // Slack - [/(?:slack(?=.+electron|.+ios)|chatlyio)\/([\d\.]+)/i], - [VERSION, [NAME, 'Slack'], [TYPE, INAPP]], + /chatlyio\/([\d\.]+)/i], + [VERSION, [NAME, 'Slack'], [TYPE, INAPP]], [ + + // TikTok Lite + /ultralite app_version\/([\w\.]+)/i], + [VERSION, [NAME, 'TikTok Lite'], [TYPE, INAPP]], [ + + // VS Code + /\) code\/([\d\.]+).+electron\//i], + [VERSION, [NAME, 'VS Code'], [TYPE, INAPP]], [ // Yahoo! Japan - [/jp\.co\.yahoo\.(?:android\.yjtop|ipn\.appli)\/([\d\.]+)/i], + /jp\.co\.yahoo\.(?:android\.yjtop|ipn\.appli)\/([\d\.]+)/i], [VERSION, [NAME, 'Yahoo! Japan'], [TYPE, INAPP]] ] }); @@ -332,8 +370,10 @@ const Libraries = Object.freeze({ browser : [ // Apache-HttpClient/Axios/go-http-client/got/GuzzleHttp/Java[-HttpClient]/jsdom/libwww-perl/lua-resty-http/Needle/node-fetch/OkHttp/PHP-SOAP/PostmanRuntime/python-urllib/python-requests/Scrapy/superagent [ - /^(apache-httpclient|axios|(?:go|java)-http-client|got|guzzlehttp|java|libwww-perl|lua-resty-http|needle|node-(?:fetch|superagent)|okhttp|php-soap|postmanruntime|python-(?:urllib|requests)|scrapy)\/([\w\.]+)/i, - /(jsdom|(?<=\()java)\/([\w\.]+)/i + /^(apache-httpclient|axios|(?:go|java)-http-client|got|guzzlehttp|java|libwww-perl|lua-resty-http|needle|node-(?:fetch|superagent)|okhttp|php-soap|postmanruntime|python-(?:httpx|urllib[23]?|requests)|scrapy)\/([\w\.]+)/i, + /(adobeair|aiohttp|jsdom)\/([\w\.]+)/i, + /(nutch)-([\w\.-]+)(\(|$)/i, + /\((java)\/([\w\.]+)/i ], [NAME, VERSION, [TYPE, LIBRARY]] ] }); diff --git a/src/helpers/ua-parser-helpers.d.ts b/src/helpers/ua-parser-helpers.d.ts index 4b6c808..fc53c61 100644 --- a/src/helpers/ua-parser-helpers.d.ts +++ b/src/helpers/ua-parser-helpers.d.ts @@ -1,4 +1,4 @@ -// Type definitions for Helpers submodule of UAParser.js v2.0.3 +// Type definitions for Helpers submodule of UAParser.js v2.0.4 // Project: https://github.com/faisalman/ua-parser-js // Definitions by: Faisal Salman diff --git a/src/helpers/ua-parser-helpers.js b/src/helpers/ua-parser-helpers.js index 5e6993d..330a654 100644 --- a/src/helpers/ua-parser-helpers.js +++ b/src/helpers/ua-parser-helpers.js @@ -1,5 +1,5 @@ /////////////////////////////////////////////// -/* Helpers for UAParser.js v2.0.3 +/* Helpers for UAParser.js v2.0.4 https://github.com/faisalman/ua-parser-js Author: Faisal Salman UAParser.js PRO Enterprise License */ @@ -110,6 +110,9 @@ const isAIBot = (resultOrUA) => [ // You.com 'youbot', + // Zhipu AI + 'chatglm-spider', + // Zyte 'scrapy' diff --git a/src/helpers/ua-parser-helpers.mjs b/src/helpers/ua-parser-helpers.mjs index 6ddbb94..e235544 100644 --- a/src/helpers/ua-parser-helpers.mjs +++ b/src/helpers/ua-parser-helpers.mjs @@ -3,7 +3,7 @@ // Source: /src/helpers/ua-parser-helpers.js /////////////////////////////////////////////// -/* Helpers for UAParser.js v2.0.3 +/* Helpers for UAParser.js v2.0.4 https://github.com/faisalman/ua-parser-js Author: Faisal Salman UAParser.js PRO Enterprise License */ @@ -114,6 +114,9 @@ const isAIBot = (resultOrUA) => [ // You.com 'youbot', + // Zhipu AI + 'chatglm-spider', + // Zyte 'scrapy' diff --git a/src/main/ua-parser.d.ts b/src/main/ua-parser.d.ts index 6c7c9f8..9533b68 100644 --- a/src/main/ua-parser.d.ts +++ b/src/main/ua-parser.d.ts @@ -1,4 +1,4 @@ -// Type definitions for UAParser.js v2.0.3 +// Type definitions for UAParser.js v2.0.4 // Project: https://github.com/faisalman/ua-parser-js // Definitions by: Faisal Salman diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index e001ec5..7b699ab 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////////// -/* UAParser.js v2.0.3 +/* UAParser.js v2.0.4 Copyright © 2012-2025 Faisal Salman UAParser.js PRO Enterprise License *//* Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data. @@ -19,7 +19,7 @@ // Constants ///////////// - var LIBVERSION = '2.0.3', + var LIBVERSION = '2.0.4', UA_MAX_LENGTH = 500, USER_AGENT = 'user-agent', EMPTY = '', @@ -152,11 +152,11 @@ has = function (str1, str2) { if (typeof str1 === OBJ_TYPE && str1.length > 0) { for (var i in str1) { - if (lowerize(str1[i]) == lowerize(str2)) return true; + if (lowerize(str2) == lowerize(str1[i])) return true; } return false; } - return isString(str1) ? lowerize(str2).indexOf(lowerize(str1)) !== -1 : false; + return isString(str1) ? lowerize(str2) == lowerize(str1) : false; }, isExtensions = function (obj, deep) { for (var prop in obj) { @@ -247,17 +247,25 @@ // assign given value, ignore regex match this[q[0]] = q[1]; } - } else if (q.length === 3) { - // check whether function or regex + } else if (q.length >= 3) { + // Check whether q[1] FUNCTION or REGEX if (typeof q[1] === FUNC_TYPE && !(q[1].exec && q[1].test)) { - // call function (usually string mapper) - this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined; + if (q.length > 3) { + this[q[0]] = match ? q[1].apply(this, q.slice(2)) : undefined; + } else { + // call function (usually string mapper) + this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined; + } } else { - // sanitize match using given regex - this[q[0]] = match ? match.replace(q[1], q[2]) : undefined; + if (q.length == 3) { + // sanitize match using given regex + this[q[0]] = match ? match.replace(q[1], q[2]) : undefined; + } else if (q.length == 4) { + this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined; + } else if (q.length > 4) { + this[q[0]] = match ? q[3].apply(this, [match.replace(q[1], q[2])].concat(q.slice(4))) : undefined; + } } - } else if (q.length === 4) { - this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined; } } else { this[q] = match ? match : undefined; @@ -291,17 +299,17 @@ ////////////// var windowsVersionMap = { - 'ME' : '4.90', - 'NT 3.11' : 'NT3.51', - 'NT 4.0' : 'NT4.0', - '2000' : 'NT 5.0', - 'XP' : ['NT 5.1', 'NT 5.2'], - 'Vista' : 'NT 6.0', - '7' : 'NT 6.1', - '8' : 'NT 6.2', - '8.1' : 'NT 6.3', - '10' : ['NT 6.4', 'NT 10.0'], - 'RT' : 'ARM' + 'ME' : '4.90', + 'NT 3.51': '3.51', + 'NT 4.0': '4.0', + '2000' : ['5.0', '5.01'], + 'XP' : ['5.1', '5.2'], + 'Vista' : '6.0', + '7' : '6.1', + '8' : '6.2', + '8.1' : '6.3', + '10' : ['6.4', '10.0'], + 'NT' : '' }, formFactorsMap = { @@ -313,6 +321,18 @@ 'xr' : ['VR', 'XR'], '?' : ['Desktop', 'Unknown'], '*' : undefined + }, + + browserHintsMap = { + 'Chrome' : 'Google Chrome', + 'Edge' : 'Microsoft Edge', + 'Edge WebView2' : 'Microsoft Edge WebView2', + 'Chrome WebView': 'Android WebView', + 'Chrome Headless':'HeadlessChrome', + 'Huawei Browser': 'HuaweiBrowser', + 'MIUI Browser' : 'Miui Browser', + 'Opera Mobi' : 'OperaMobile', + 'Yandex' : 'YaBrowser' }; ////////////// @@ -326,7 +346,9 @@ // Most common regardless engine /\b(?:crmo|crios)\/([\w\.]+)/i // Chrome for Android/iOS ], [VERSION, [NAME, PREFIX_MOBILE + 'Chrome']], [ - /edg(?:e|ios|a)?\/([\w\.]+)/i // Microsoft Edge + /webview.+edge\/([\w\.]+)/i // Microsoft Edge + ], [VERSION, [NAME, EDGE+' WebView']], [ + /edg(?:e|ios|a)?\/([\w\.]+)/i ], [VERSION, [NAME, 'Edge']], [ // Presto based @@ -418,7 +440,6 @@ // WebView /((?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/([\w\.]+);)/i // Facebook App for iOS & Android ], [[NAME, FACEBOOK], VERSION, [TYPE, INAPP]], [ - /(Klarna)\/([\w\.]+)/i, // Klarna Shopping Browser for iOS & Android /(kakao(?:talk|story))[\/ ]([\w\.]+)/i, // Kakao App /(naver)\(.*?(\d+\.[\w\.]+).*\)/i, // Naver InApp /(daum)apps[\/ ]([\w\.]+)/i, // Daum App @@ -426,7 +447,7 @@ /\b(line)\/([\w\.]+)\/iab/i, // Line App for Android /(alipay)client\/([\w\.]+)/i, // Alipay /(twitter)(?:and| f.+e\/([\w\.]+))/i, // Twitter - /(instagram|snapchat)[\/ ]([-\w\.]+)/i // Instagram/Snapchat + /(instagram|snapchat|klarna)[\/ ]([-\w\.]+)/i // Instagram/Snapchat/Klarna ], [NAME, VERSION, [TYPE, INAPP]], [ /\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS ], [VERSION, [NAME, 'GSA'], [TYPE, INAPP]], [ @@ -441,6 +462,9 @@ /headlesschrome(?:\/([\w\.]+)| )/i // Chrome Headless ], [VERSION, [NAME, CHROME+' Headless']], [ + /wv\).+chrome\/([\w\.]+).+edgw\//i // Edge WebView2 + ], [VERSION, [NAME, EDGE+' WebView2']], [ + / wv\).+(chrome)\/([\w\.]+)/i // Chrome WebView ], [[NAME, CHROME+' WebView'], VERSION], [ @@ -533,7 +557,7 @@ /\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]], [ /\b((?:s[cgp]h|gt|sm)-(?![lr])\w+|sc[g-]?[\d]+a?|galaxy nexus)/i, - /samsung[- ]((?!sm-[lr])[-\w]+)/i, + /samsung[- ]((?!sm-[lr]|browser)[-\w]+)/i, /sec-(sgh\w+)/i ], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [ @@ -578,16 +602,22 @@ / ([\w ]+) miui\/v?\d/i ], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [ + // OnePlus + /droid.+; (cph2[3-6]\d[13579]|((gm|hd)19|(ac|be|in|kb)20|(d[en]|eb|le|mt)21|ne22)[0-2]\d|p[g-k]\w[1m]10)\b/i, + /(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i + ], [MODEL, [VENDOR, ONEPLUS], [TYPE, MOBILE]], [ + // OPPO /; (\w+) bui.+ oppo/i, /\b(cph[12]\d{3}|p(?:af|c[al]|d\w|e[ar])[mt]\d0|x9007|a101op)\b/i ], [MODEL, [VENDOR, OPPO], [TYPE, MOBILE]], [ /\b(opd2(\d{3}a?))(?: bui|\))/i - ], [MODEL, [VENDOR, strMapper, { 'OnePlus' : ['304', '403', '203'], '*' : OPPO }], [TYPE, TABLET]], [ + ], [MODEL, [VENDOR, strMapper, { 'OnePlus' : ['203', '304', '403', '404', '413', '415'], '*' : OPPO }], [TYPE, TABLET]], [ + + // BLU + /(vivo (5r?|6|8l?|go|one|s|x[il]?[2-4]?)[\w\+ ]*)(?: bui|\))/i // Vivo series + ], [MODEL, [VENDOR, 'BLU'], [TYPE, MOBILE]], [ - // BLU Vivo Series - /(vivo (5r?|6|8l?|go|one|s|x[il]?[2-4]?)[\w\+ ]*)(?: bui|\))/i - ], [MODEL, [VENDOR, 'BLU'], [TYPE, MOBILE]], [ // Vivo /; vivo (\w+)(?: bui|\))/i, /\b(v[12]\d{3}\w?[at])(?: bui|;)/i @@ -597,10 +627,17 @@ /\b(rmx[1-3]\d{3})(?: bui|;|\))/i ], [MODEL, [VENDOR, 'Realme'], [TYPE, MOBILE]], [ + // Lenovo + /(ideatab[-\w ]+|602lv|d-42a|a101lv|a2109a|a3500-hv|s[56]000|pb-6505[my]|tb-?x?\d{3,4}(?:f[cu]|xu|[av])|yt\d?-[jx]?\d+[lfmx])( bui|;|\)|\/)/i, + /lenovo ?(b[68]0[08]0-?[hf]?|tab(?:[\w- ]+?)|tb[\w-]{6,7})( bui|;|\)|\/)/i + ], [MODEL, [VENDOR, LENOVO], [TYPE, TABLET]], [ + /lenovo[-_ ]?([-\w ]+?)(?: bui|\)|\/)/i + ], [MODEL, [VENDOR, LENOVO], [TYPE, MOBILE]], [ + // Motorola /\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\b[\w ]+build\//i, - /\bmot(?:orola)?[- ](\w*)/i, - /((?:moto(?! 360)[\w\(\) ]+|xt\d{3,4}|nexus 6)(?= bui|\)))/i + /\bmot(?:orola)?[- ]([\w\s]+)(\)| bui)/i, + /((?:moto(?! 360)[-\w\(\) ]+|xt\d{3,4}[cgkosw\+]?[-\d]*|nexus 6)(?= bui|\)))/i ], [MODEL, [VENDOR, MOTOROLA], [TYPE, MOBILE]], [ /\b(mz60\d|xoom[2 ]{0,2}) build\//i ], [MODEL, [VENDOR, MOTOROLA], [TYPE, TABLET]], [ @@ -609,15 +646,10 @@ /((?=lg)?[vl]k\-?\d{3}) bui| 3\.[-\w; ]{10}lg?-([06cv9]{3,4})/i ], [MODEL, [VENDOR, LG], [TYPE, TABLET]], [ /(lm(?:-?f100[nv]?|-[\w\.]+)(?= bui|\))|nexus [45])/i, - /\blg[-e;\/ ]+(?!.*(?:browser|netcast|android tv|watch))(\w+)/i, + /\blg[-e;\/ ]+(?!.*(?:browser|netcast|android tv|watch|webos))(\w+)/i, /\blg-?([\d\w]+) bui/i ], [MODEL, [VENDOR, LG], [TYPE, MOBILE]], [ - // Lenovo - /(ideatab[-\w ]+|602lv|d-42a|a101lv|a2109a|a3500-hv|s[56]000|pb-6505[my]|tb-?x?\d{3,4}(?:f[cu]|xu|[av])|yt\d?-[jx]?\d+[lfmx])( bui|;|\)|\/)/i, - /lenovo ?(b[68]0[08]0-?[hf]?|tab(?:[\w- ]+?)|tb[\w-]{6,7})( bui|;|\)|\/)/i - ], [MODEL, [VENDOR, LENOVO], [TYPE, TABLET]], [ - // Nokia /(nokia) (t[12][01])/i ], [VENDOR, MODEL, [TYPE, TABLET]], [ @@ -628,21 +660,19 @@ // Google /(pixel (c|tablet))\b/i // Google Pixel C/Tablet ], [MODEL, [VENDOR, GOOGLE], [TYPE, TABLET]], [ - /droid.+; (pixel[\daxl ]{0,6})(?: bui|\))/i // Google Pixel + // Google Pixel + /droid.+;(?: google)? (g(01[13]a|020[aem]|025[jn]|1b60|1f8f|2ybb|4s1m|576d|5nz6|8hhn|8vou|a02099|c15s|d1yq|e2ae|ec77|gh2x|kv4x|p4bc|pj41|r83y|tt9q|ur25|wvk6)|pixel[\d ]*a?( pro)?( xl)?( fold)?( \(5g\))?)( bui|\))/i ], [MODEL, [VENDOR, GOOGLE], [TYPE, MOBILE]], [ + /(google) (pixelbook( go)?)/i + ], [VENDOR, MODEL], [ // Sony - /droid.+; (a?\d[0-2]{2}so|[c-g]\d{4}|so[-gl]\w+|xq-a\w[4-7][12])(?= bui|\).+chrome\/(?![1-6]{0,1}\d\.))/i + /droid.+; (a?\d[0-2]{2}so|[c-g]\d{4}|so[-gl]\w+|xq-\w\w\d\d)(?= bui|\).+chrome\/(?![1-6]{0,1}\d\.))/i ], [MODEL, [VENDOR, SONY], [TYPE, MOBILE]], [ /sony tablet [ps]/i, /\b(?:sony)?sgp\w+(?: bui|\))/i ], [[MODEL, 'Xperia Tablet'], [VENDOR, SONY], [TYPE, TABLET]], [ - // OnePlus - / (kb2005|in20[12]5|be20[12][59])\b/i, - /(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i - ], [MODEL, [VENDOR, ONEPLUS], [TYPE, MOBILE]], [ - // Amazon /(alexa)webm/i, /(kf[a-z]{2}wi|aeo(?!bc)\w\w)( bui|\))/i, // Kindle Fire without Silk / Echo Show @@ -713,7 +743,7 @@ ], [MODEL, [VENDOR, 'Smartfren'], [TYPE, MOBILE]], [ // Nothing - /droid.+; (a(?:015|06[35]|142p?))/i + /droid.+; (a(in)?(0(15|59|6[35])|142)p?)/i ], [MODEL, [VENDOR, 'Nothing'], [TYPE, MOBILE]], [ // Archos @@ -724,17 +754,20 @@ /; (ac[3-6]\d\w{2,8})( b|\))/i ], [MODEL, [VENDOR, 'Archos'], [TYPE, MOBILE]], [ + // HMD + /; (n159v)/i + ], [MODEL, [VENDOR, 'HMD'], [TYPE, MOBILE]], [ + // MIXED /(imo) (tab \w+)/i, // IMO - /(infinix) (x1101b?)/i // Infinix XPad + /(infinix|tecno) (x1101b?|p904|dp(7c|8d|10a)( pro)?|p70[1-3]a?|p904|t1101)/i // Infinix XPad / Tecno ], [VENDOR, MODEL, [TYPE, TABLET]], [ - /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus(?! zenw)|dell|jolla|meizu|motorola|polytron|infinix|tecno|micromax|advan)[-_ ]?([-\w]*)/i, - // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron/Infinix/Tecno/Micromax/Advan - /; (blu|hmd|imo|tcl)[_ ]([\w\+ ]+?)(?: bui|\)|; r)/i, // BLU/HMD/IMO/TCL + /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus(?! zenw)|dell|jolla|meizu|motorola|polytron|tecno|micromax|advan)[-_ ]?([-\w]*)/i, + // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron/Tecno/Micromax/Advan + /; (blu|hmd|imo|infinix|lava|oneplus|tcl)[_ ]([\w\+ ]+?)(?: bui|\)|; r)/i, // BLU/HMD/IMO/Infinix/Lava/OnePlus/TCL /(hp) ([\w ]+\w)/i, // HP iPAQ /(microsoft); (lumia[\w ]+)/i, // Microsoft Lumia - /(lenovo)[-_ ]?([-\w ]+?)(?: bui|\)|\/)/i, // Lenovo /(oppo) ?([\w ]+) bui/i // OPPO ], [VENDOR, MODEL, [TYPE, MOBILE]], [ @@ -766,6 +799,7 @@ ], [VENDOR, [TYPE, SMARTTV]], [ /hbbtv.+maple;(\d+)/i ], [[MODEL, /^/, 'SmartTV'], [VENDOR, SAMSUNG], [TYPE, SMARTTV]], [ + /(vizio)(?: |.+model\/)(\w+-\w+)/i, // Vizio /tcast.+(lg)e?. ([-\w]+)/i // LG SmartTV ], [VENDOR, MODEL, [TYPE, SMARTTV]], [ /(nux; netcast.+smarttv|lg (netcast\.tv-201\d|android tv))/i @@ -797,26 +831,27 @@ ], [VENDOR, MODEL, [TYPE, SMARTTV]], [ /\b(roku)[\dx]*[\)\/]((?:dvp-)?[\d\.]*)/i, // Roku /hbbtv\/\d+\.\d+\.\d+ +\([\w\+ ]*; *([\w\d][^;]*);([^;]*)/i // HbbTV devices - ], [[VENDOR, trim], [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:)\b/i + /\b(android tv|smart[- ]?tv|opera tv|tv; rv:|large screen[\w ]+safari)\b/i ], [[TYPE, SMARTTV]], [ /////////////////// // CONSOLES /////////////////// - /(ouya)/i, // Ouya - /(nintendo) (\w+)/i // Nintendo - ], [VENDOR, MODEL, [TYPE, CONSOLE]], [ - /droid.+; (shield)( bui|\))/i // Nvidia Portable - ], [MODEL, [VENDOR, NVIDIA], [TYPE, CONSOLE]], [ /(playstation \w+)/i // Playstation ], [MODEL, [VENDOR, SONY], [TYPE, CONSOLE]], [ /\b(xbox(?: one)?(?!; xbox))[\); ]/i // Microsoft Xbox ], [MODEL, [VENDOR, MICROSOFT], [TYPE, CONSOLE]], [ + /(ouya)/i, // Ouya + /(nintendo) (\w+)/i, // Nintendo + /(retroid) (pocket ([^\)]+))/i // Retroid Pocket + ], [VENDOR, MODEL, [TYPE, CONSOLE]], [ + /droid.+; (shield)( bui|\))/i // Nvidia Portable + ], [MODEL, [VENDOR, NVIDIA], [TYPE, CONSOLE]], [ /////////////////// // WEARABLES @@ -852,6 +887,8 @@ ], [VENDOR, MODEL, [TYPE, XR]], [ /(quest( \d| pro)?s?).+vr/i // Meta Quest ], [MODEL, [VENDOR, FACEBOOK], [TYPE, XR]], [ + /mobile vr; rv.+firefox/i // Unidentifiable VR device using Firefox Reality / Wolvic + ], [[TYPE, XR]], [ /////////////////// // EMBEDDED @@ -863,7 +900,7 @@ ], [MODEL, [VENDOR, AMAZON], [TYPE, EMBEDDED]], [ /(homepod).+mac os/i // Apple HomePod ], [MODEL, [VENDOR, APPLE], [TYPE, EMBEDDED]], [ - /windows iot/i + /windows iot/i // Unidentifiable embedded device using Windows IoT ], [[TYPE, EMBEDDED]], [ //////////////////// @@ -909,14 +946,17 @@ os : [[ // Windows - /microsoft (windows) (vista|xp)/i // Windows (iTunes) + /(windows nt) (6\.[23]); arm/i // Windows RT + ], [[NAME, /N/, 'R'], [VERSION, strMapper, windowsVersionMap]], [ + /(windows (?:phone|mobile|iot))(?: os)?[\/ ]?([\d\.]*( se)?)/i, // Windows IoT/Mobile/Phone + // Windows NT/3.1/95/98/ME/2000/XP/Vista/7/8/8.1/10/11 + /(windows)[\/ ](1[01]|2000|3\.1|7|8(\.1)?|9[58]|me|server 20\d\d( r2)?|vista|xp)/i + ], [NAME, VERSION], [ + /windows nt ?([\d\.\)]*)(?!.+xbox)/i, + /\bwin(?=3| ?9|n)(?:nt| 9x )?([\d\.;]*)/i + ], [[VERSION, /(;|\))/g, '', strMapper, windowsVersionMap], [NAME, WINDOWS]], [ + /(windows ce)\/?([\d\.]*)/i // Windows CE ], [NAME, VERSION], [ - /(windows (?:phone(?: os)?|mobile|iot))[\/ ]?([\d\.\w ]*)/i // Windows Phone - ], [NAME, [VERSION, strMapper, windowsVersionMap]], [ - /windows nt 6\.2; (arm)/i, // Windows RT - /windows[\/ ]([ntce\d\. ]+\w)(?!.+xbox)/i, - /(?:win(?=3|9|n)|win 9x )([nt\d\.]+)/i - ], [[VERSION, strMapper, windowsVersionMap], [NAME, WINDOWS]], [ // iOS/macOS /[adehimnop]{4,7}\b(?:.*os ([\w]+) like mac|; opera)/i, // iOS @@ -924,7 +964,7 @@ /cfnetwork\/.+darwin/i ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [ /(mac os x) ?([\w\. ]*)/i, - /(macintosh|mac_powerpc\b)(?!.+haiku)/i // Mac OS + /(macintosh|mac_powerpc\b)(?!.+(haiku|morphos))/i // Mac OS ], [[NAME, 'macOS'], [VERSION, /_/g, '.']], [ // Google Chromecast @@ -940,12 +980,13 @@ ], [VERSION, [NAME, CHROMECAST]], [ // Mobile OSes - /droid ([\w\.]+)\b.+(android[- ]x86|harmonyos)/i // Android-x86/HarmonyOS + /droid ([\w\.]+)\b.+(android[- ]x86)/i // Android-x86 ], [VERSION, NAME], [ /(ubuntu) ([\w\.]+) like android/i // Ubuntu Touch ], [[NAME, /(.+)/, '$1 Touch'], VERSION], [ + /(harmonyos)[\/ ]?([\d\.]*)/i, // HarmonyOS // Android/Blackberry/WebOS/QNX/Bada/RIM/KaiOS/Maemo/MeeGo/S40/Sailfish OS/OpenHarmony/Tizen - /(android|bada|blackberry|kaios|maemo|meego|openharmony|qnx|rim tablet os|sailfish|series40|symbian|tizen|webos)\w*[-\/\.; ]?([\d\.]*)/i + /(android|bada|blackberry|kaios|maemo|meego|openharmony|qnx|rim tablet os|sailfish|series40|symbian|tizen)\w*[-\/\.; ]?([\d\.]*)/i ], [NAME, VERSION], [ /\(bb(10);/i // BlackBerry 10 ], [VERSION, [NAME, BLACKBERRY]], [ @@ -953,9 +994,12 @@ ], [VERSION, [NAME, 'Symbian']], [ /mozilla\/[\d\.]+ \((?:mobile|tablet|tv|mobile; [\w ]+); rv:.+ gecko\/([\w\.]+)/i // Firefox OS ], [VERSION, [NAME, FIREFOX+' OS']], [ - /web0s;.+rt(tv)/i, - /\b(?:hp)?wos(?:browser)?\/([\w\.]+)/i // WebOS + /\b(?:hp)?wos(?:browser)?\/([\w\.]+)/i, // WebOS + /webos(?:[ \/]?|\.tv-20(?=2[2-9]))(\d[\d\.]*)/i ], [VERSION, [NAME, 'webOS']], [ + /web0s;.+?(?:chr[o0]me|safari)\/(\d+)/i + // https://webostv.developer.lge.com/develop/specifications/web-api-and-web-engine + ], [[VERSION, strMapper, {'25':'120','24':'108','23':'94','22':'87','6':'79','5':'68','4':'53','3':'38','2':'538','1':'537','*':'TV'}], [NAME, 'webOS']], [ /watch(?: ?os[,\/]|\d,\d\/)([\d\.]+)/i // watchOS ], [VERSION, [NAME, 'watchOS']], [ @@ -975,20 +1019,20 @@ // Other /\b(joli|palm)\b ?(?:os)?\/?([\w\.]*)/i, // Joli/Palm - /(mint)[\/\(\) ]?(\w*)/i, // Mint - /(mageia|vectorlinux)[; ]/i, // Mageia/VectorLinux - /([kxln]?ubuntu|debian|suse|opensuse|gentoo|arch(?= linux)|slackware|fedora|mandriva|centos|pclinuxos|red ?hat|zenwalk|linpus|raspbian|plan 9|minix|risc os|contiki|deepin|manjaro|elementary os|sabayon|linspire)(?: gnu\/linux)?(?: enterprise)?(?:[- ]linux)?(?:-gnu)?[-\/ ]?(?!chrom|package)([-\w\.]*)/i, - // Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware/Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus/Raspbian/Plan9/Minix/RISCOS/Contiki/Deepin/Manjaro/elementary/Sabayon/Linspire - /(hurd|linux)(?: arm\w*| x86\w*| ?)([\w\.]*)/i, // Hurd/Linux + /linux.+(mint)[\/\(\) ]?([\w\.]*)/i, // Mint + /(mageia|vectorlinux|fuchsia|arcaos|arch(?= ?linux))[;l ]([\d\.]*)/i, // Mageia/VectorLinux/Fuchsia/ArcaOS/Arch + /([kxln]?ubuntu|debian|suse|opensuse|gentoo|slackware|fedora|mandriva|centos|pclinuxos|red ?hat|zenwalk|linpus|raspbian|plan 9|minix|risc os|contiki|deepin|manjaro|elementary os|sabayon|linspire|knoppix)(?: gnu[\/ ]linux)?(?: enterprise)?(?:[- ]linux)?(?:-gnu)?[-\/ ]?(?!chrom|package)([-\w\.]*)/i, + // Ubuntu/Debian/SUSE/Gentoo/Slackware/Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus/Raspbian/Plan9/Minix/RISCOS/Contiki/Deepin/Manjaro/elementary/Sabayon/Linspire/Knoppix + /((?:open)?solaris)[-\/ ]?([\w\.]*)/i, // Solaris + /\b(aix)[; ]([1-9\.]{0,4})/i, // AIX + /(hurd|linux|morphos)(?: (?:arm|x86|ppc)\w*| ?)([\w\.]*)/i, // Hurd/Linux/MorphOS /(gnu) ?([\w\.]*)/i, // GNU /\b([-frentopcghs]{0,5}bsd|dragonfly)[\/ ]?(?!amd|[ix346]{1,2}86)([\w\.]*)/i, // FreeBSD/NetBSD/OpenBSD/PC-BSD/GhostBSD/DragonFly - /(haiku) (\w+)/i // Haiku + /(haiku) ?(r\d)?/i // Haiku ], [NAME, VERSION], [ - /(sunos) ?([\w\.\d]*)/i // Solaris + /(sunos) ?([\d\.]*)/i // Solaris ], [[NAME, 'Solaris'], VERSION], [ - /((?:open)?solaris)[-\/ ]?([\w\.]*)/i, // Solaris - /(aix) ((\d)(?=\.|\)| )[\w\.])*/i, // AIX - /\b(beos|os\/2|amigaos|morphos|openvms|fuchsia|hp-ux|serenityos)/i, // BeOS/OS2/AmigaOS/MorphOS/OpenVMS/Fuchsia/HP-UX/SerenityOS + /\b(beos|os\/2|amigaos|openvms|hp-ux|serenityos)/i, // BeOS/OS2/AmigaOS/OpenVMS/HP-UX/SerenityOS /(unix) ?([\w\.]*)/i // UNIX ], [NAME, VERSION] ] @@ -1222,21 +1266,20 @@ for (var i in brands) { var brandName = brands[i].brand || brands[i], brandVersion = brands[i].version; - if (this.itemType == UA_BROWSER && !/not.a.brand/i.test(brandName) && (!prevName || (/chrom/i.test(prevName) && brandName != CHROMIUM))) { - brandName = strMapper(brandName, { - 'Chrome' : 'Google Chrome', - 'Edge' : 'Microsoft Edge', - 'Chrome WebView' : 'Android WebView', - 'Chrome Headless' : 'HeadlessChrome', - 'Huawei Browser' : 'HuaweiBrowser', - 'MIUI Browser' : 'Miui Browser', - 'Opera Mobi' : 'OperaMobile', - 'Yandex' : 'YaBrowser' - }); - this.set(NAME, brandName) - .set(VERSION, brandVersion) - .set(MAJOR, majorize(brandVersion)); - prevName = brandName; + if (this.itemType == UA_BROWSER && + !/not.a.brand/i.test(brandName) && + (!prevName || + (/Chrom/.test(prevName) && brandName != CHROMIUM) || + (prevName == EDGE && /WebView2/.test(brandName)) + )) { + brandName = strMapper(brandName, browserHintsMap); + prevName = this.get(NAME); + if (!(prevName && !/Chrom/.test(prevName) && /Chrom/.test(brandName))) { + this.set(NAME, brandName) + .set(VERSION, brandVersion) + .set(MAJOR, majorize(brandVersion)); + } + prevName = brandName; } if (this.itemType == UA_ENGINE && brandName == CHROMIUM) { this.set(VERSION, brandVersion); diff --git a/src/main/ua-parser.mjs b/src/main/ua-parser.mjs index d652f6e..5b55c74 100644 --- a/src/main/ua-parser.mjs +++ b/src/main/ua-parser.mjs @@ -3,7 +3,7 @@ // Source: /src/main/ua-parser.js ///////////////////////////////////////////////////////////////////////////////// -/* UAParser.js v2.0.3 +/* UAParser.js v2.0.4 Copyright © 2012-2025 Faisal Salman UAParser.js PRO Enterprise License *//* Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data. @@ -21,7 +21,7 @@ // Constants ///////////// - var LIBVERSION = '2.0.3', + var LIBVERSION = '2.0.4', UA_MAX_LENGTH = 500, USER_AGENT = 'user-agent', EMPTY = '', @@ -154,11 +154,11 @@ has = function (str1, str2) { if (typeof str1 === OBJ_TYPE && str1.length > 0) { for (var i in str1) { - if (lowerize(str1[i]) == lowerize(str2)) return true; + if (lowerize(str2) == lowerize(str1[i])) return true; } return false; } - return isString(str1) ? lowerize(str2).indexOf(lowerize(str1)) !== -1 : false; + return isString(str1) ? lowerize(str2) == lowerize(str1) : false; }, isExtensions = function (obj, deep) { for (var prop in obj) { @@ -249,17 +249,25 @@ // assign given value, ignore regex match this[q[0]] = q[1]; } - } else if (q.length === 3) { - // check whether function or regex + } else if (q.length >= 3) { + // Check whether q[1] FUNCTION or REGEX if (typeof q[1] === FUNC_TYPE && !(q[1].exec && q[1].test)) { - // call function (usually string mapper) - this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined; + if (q.length > 3) { + this[q[0]] = match ? q[1].apply(this, q.slice(2)) : undefined; + } else { + // call function (usually string mapper) + this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined; + } } else { - // sanitize match using given regex - this[q[0]] = match ? match.replace(q[1], q[2]) : undefined; + if (q.length == 3) { + // sanitize match using given regex + this[q[0]] = match ? match.replace(q[1], q[2]) : undefined; + } else if (q.length == 4) { + this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined; + } else if (q.length > 4) { + this[q[0]] = match ? q[3].apply(this, [match.replace(q[1], q[2])].concat(q.slice(4))) : undefined; + } } - } else if (q.length === 4) { - this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined; } } else { this[q] = match ? match : undefined; @@ -293,17 +301,17 @@ ////////////// var windowsVersionMap = { - 'ME' : '4.90', - 'NT 3.11' : 'NT3.51', - 'NT 4.0' : 'NT4.0', - '2000' : 'NT 5.0', - 'XP' : ['NT 5.1', 'NT 5.2'], - 'Vista' : 'NT 6.0', - '7' : 'NT 6.1', - '8' : 'NT 6.2', - '8.1' : 'NT 6.3', - '10' : ['NT 6.4', 'NT 10.0'], - 'RT' : 'ARM' + 'ME' : '4.90', + 'NT 3.51': '3.51', + 'NT 4.0': '4.0', + '2000' : ['5.0', '5.01'], + 'XP' : ['5.1', '5.2'], + 'Vista' : '6.0', + '7' : '6.1', + '8' : '6.2', + '8.1' : '6.3', + '10' : ['6.4', '10.0'], + 'NT' : '' }, formFactorsMap = { @@ -315,6 +323,18 @@ 'xr' : ['VR', 'XR'], '?' : ['Desktop', 'Unknown'], '*' : undefined + }, + + browserHintsMap = { + 'Chrome' : 'Google Chrome', + 'Edge' : 'Microsoft Edge', + 'Edge WebView2' : 'Microsoft Edge WebView2', + 'Chrome WebView': 'Android WebView', + 'Chrome Headless':'HeadlessChrome', + 'Huawei Browser': 'HuaweiBrowser', + 'MIUI Browser' : 'Miui Browser', + 'Opera Mobi' : 'OperaMobile', + 'Yandex' : 'YaBrowser' }; ////////////// @@ -328,7 +348,9 @@ // Most common regardless engine /\b(?:crmo|crios)\/([\w\.]+)/i // Chrome for Android/iOS ], [VERSION, [NAME, PREFIX_MOBILE + 'Chrome']], [ - /edg(?:e|ios|a)?\/([\w\.]+)/i // Microsoft Edge + /webview.+edge\/([\w\.]+)/i // Microsoft Edge + ], [VERSION, [NAME, EDGE+' WebView']], [ + /edg(?:e|ios|a)?\/([\w\.]+)/i ], [VERSION, [NAME, 'Edge']], [ // Presto based @@ -420,7 +442,6 @@ // WebView /((?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/([\w\.]+);)/i // Facebook App for iOS & Android ], [[NAME, FACEBOOK], VERSION, [TYPE, INAPP]], [ - /(Klarna)\/([\w\.]+)/i, // Klarna Shopping Browser for iOS & Android /(kakao(?:talk|story))[\/ ]([\w\.]+)/i, // Kakao App /(naver)\(.*?(\d+\.[\w\.]+).*\)/i, // Naver InApp /(daum)apps[\/ ]([\w\.]+)/i, // Daum App @@ -428,7 +449,7 @@ /\b(line)\/([\w\.]+)\/iab/i, // Line App for Android /(alipay)client\/([\w\.]+)/i, // Alipay /(twitter)(?:and| f.+e\/([\w\.]+))/i, // Twitter - /(instagram|snapchat)[\/ ]([-\w\.]+)/i // Instagram/Snapchat + /(instagram|snapchat|klarna)[\/ ]([-\w\.]+)/i // Instagram/Snapchat/Klarna ], [NAME, VERSION, [TYPE, INAPP]], [ /\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS ], [VERSION, [NAME, 'GSA'], [TYPE, INAPP]], [ @@ -443,6 +464,9 @@ /headlesschrome(?:\/([\w\.]+)| )/i // Chrome Headless ], [VERSION, [NAME, CHROME+' Headless']], [ + /wv\).+chrome\/([\w\.]+).+edgw\//i // Edge WebView2 + ], [VERSION, [NAME, EDGE+' WebView2']], [ + / wv\).+(chrome)\/([\w\.]+)/i // Chrome WebView ], [[NAME, CHROME+' WebView'], VERSION], [ @@ -535,7 +559,7 @@ /\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]], [ /\b((?:s[cgp]h|gt|sm)-(?![lr])\w+|sc[g-]?[\d]+a?|galaxy nexus)/i, - /samsung[- ]((?!sm-[lr])[-\w]+)/i, + /samsung[- ]((?!sm-[lr]|browser)[-\w]+)/i, /sec-(sgh\w+)/i ], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [ @@ -580,16 +604,22 @@ / ([\w ]+) miui\/v?\d/i ], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [ + // OnePlus + /droid.+; (cph2[3-6]\d[13579]|((gm|hd)19|(ac|be|in|kb)20|(d[en]|eb|le|mt)21|ne22)[0-2]\d|p[g-k]\w[1m]10)\b/i, + /(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i + ], [MODEL, [VENDOR, ONEPLUS], [TYPE, MOBILE]], [ + // OPPO /; (\w+) bui.+ oppo/i, /\b(cph[12]\d{3}|p(?:af|c[al]|d\w|e[ar])[mt]\d0|x9007|a101op)\b/i ], [MODEL, [VENDOR, OPPO], [TYPE, MOBILE]], [ /\b(opd2(\d{3}a?))(?: bui|\))/i - ], [MODEL, [VENDOR, strMapper, { 'OnePlus' : ['304', '403', '203'], '*' : OPPO }], [TYPE, TABLET]], [ + ], [MODEL, [VENDOR, strMapper, { 'OnePlus' : ['203', '304', '403', '404', '413', '415'], '*' : OPPO }], [TYPE, TABLET]], [ + + // BLU + /(vivo (5r?|6|8l?|go|one|s|x[il]?[2-4]?)[\w\+ ]*)(?: bui|\))/i // Vivo series + ], [MODEL, [VENDOR, 'BLU'], [TYPE, MOBILE]], [ - // BLU Vivo Series - /(vivo (5r?|6|8l?|go|one|s|x[il]?[2-4]?)[\w\+ ]*)(?: bui|\))/i - ], [MODEL, [VENDOR, 'BLU'], [TYPE, MOBILE]], [ // Vivo /; vivo (\w+)(?: bui|\))/i, /\b(v[12]\d{3}\w?[at])(?: bui|;)/i @@ -599,10 +629,17 @@ /\b(rmx[1-3]\d{3})(?: bui|;|\))/i ], [MODEL, [VENDOR, 'Realme'], [TYPE, MOBILE]], [ + // Lenovo + /(ideatab[-\w ]+|602lv|d-42a|a101lv|a2109a|a3500-hv|s[56]000|pb-6505[my]|tb-?x?\d{3,4}(?:f[cu]|xu|[av])|yt\d?-[jx]?\d+[lfmx])( bui|;|\)|\/)/i, + /lenovo ?(b[68]0[08]0-?[hf]?|tab(?:[\w- ]+?)|tb[\w-]{6,7})( bui|;|\)|\/)/i + ], [MODEL, [VENDOR, LENOVO], [TYPE, TABLET]], [ + /lenovo[-_ ]?([-\w ]+?)(?: bui|\)|\/)/i + ], [MODEL, [VENDOR, LENOVO], [TYPE, MOBILE]], [ + // Motorola /\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\b[\w ]+build\//i, - /\bmot(?:orola)?[- ](\w*)/i, - /((?:moto(?! 360)[\w\(\) ]+|xt\d{3,4}|nexus 6)(?= bui|\)))/i + /\bmot(?:orola)?[- ]([\w\s]+)(\)| bui)/i, + /((?:moto(?! 360)[-\w\(\) ]+|xt\d{3,4}[cgkosw\+]?[-\d]*|nexus 6)(?= bui|\)))/i ], [MODEL, [VENDOR, MOTOROLA], [TYPE, MOBILE]], [ /\b(mz60\d|xoom[2 ]{0,2}) build\//i ], [MODEL, [VENDOR, MOTOROLA], [TYPE, TABLET]], [ @@ -611,15 +648,10 @@ /((?=lg)?[vl]k\-?\d{3}) bui| 3\.[-\w; ]{10}lg?-([06cv9]{3,4})/i ], [MODEL, [VENDOR, LG], [TYPE, TABLET]], [ /(lm(?:-?f100[nv]?|-[\w\.]+)(?= bui|\))|nexus [45])/i, - /\blg[-e;\/ ]+(?!.*(?:browser|netcast|android tv|watch))(\w+)/i, + /\blg[-e;\/ ]+(?!.*(?:browser|netcast|android tv|watch|webos))(\w+)/i, /\blg-?([\d\w]+) bui/i ], [MODEL, [VENDOR, LG], [TYPE, MOBILE]], [ - // Lenovo - /(ideatab[-\w ]+|602lv|d-42a|a101lv|a2109a|a3500-hv|s[56]000|pb-6505[my]|tb-?x?\d{3,4}(?:f[cu]|xu|[av])|yt\d?-[jx]?\d+[lfmx])( bui|;|\)|\/)/i, - /lenovo ?(b[68]0[08]0-?[hf]?|tab(?:[\w- ]+?)|tb[\w-]{6,7})( bui|;|\)|\/)/i - ], [MODEL, [VENDOR, LENOVO], [TYPE, TABLET]], [ - // Nokia /(nokia) (t[12][01])/i ], [VENDOR, MODEL, [TYPE, TABLET]], [ @@ -630,21 +662,19 @@ // Google /(pixel (c|tablet))\b/i // Google Pixel C/Tablet ], [MODEL, [VENDOR, GOOGLE], [TYPE, TABLET]], [ - /droid.+; (pixel[\daxl ]{0,6})(?: bui|\))/i // Google Pixel + // Google Pixel + /droid.+;(?: google)? (g(01[13]a|020[aem]|025[jn]|1b60|1f8f|2ybb|4s1m|576d|5nz6|8hhn|8vou|a02099|c15s|d1yq|e2ae|ec77|gh2x|kv4x|p4bc|pj41|r83y|tt9q|ur25|wvk6)|pixel[\d ]*a?( pro)?( xl)?( fold)?( \(5g\))?)( bui|\))/i ], [MODEL, [VENDOR, GOOGLE], [TYPE, MOBILE]], [ + /(google) (pixelbook( go)?)/i + ], [VENDOR, MODEL], [ // Sony - /droid.+; (a?\d[0-2]{2}so|[c-g]\d{4}|so[-gl]\w+|xq-a\w[4-7][12])(?= bui|\).+chrome\/(?![1-6]{0,1}\d\.))/i + /droid.+; (a?\d[0-2]{2}so|[c-g]\d{4}|so[-gl]\w+|xq-\w\w\d\d)(?= bui|\).+chrome\/(?![1-6]{0,1}\d\.))/i ], [MODEL, [VENDOR, SONY], [TYPE, MOBILE]], [ /sony tablet [ps]/i, /\b(?:sony)?sgp\w+(?: bui|\))/i ], [[MODEL, 'Xperia Tablet'], [VENDOR, SONY], [TYPE, TABLET]], [ - // OnePlus - / (kb2005|in20[12]5|be20[12][59])\b/i, - /(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i - ], [MODEL, [VENDOR, ONEPLUS], [TYPE, MOBILE]], [ - // Amazon /(alexa)webm/i, /(kf[a-z]{2}wi|aeo(?!bc)\w\w)( bui|\))/i, // Kindle Fire without Silk / Echo Show @@ -715,7 +745,7 @@ ], [MODEL, [VENDOR, 'Smartfren'], [TYPE, MOBILE]], [ // Nothing - /droid.+; (a(?:015|06[35]|142p?))/i + /droid.+; (a(in)?(0(15|59|6[35])|142)p?)/i ], [MODEL, [VENDOR, 'Nothing'], [TYPE, MOBILE]], [ // Archos @@ -726,17 +756,20 @@ /; (ac[3-6]\d\w{2,8})( b|\))/i ], [MODEL, [VENDOR, 'Archos'], [TYPE, MOBILE]], [ + // HMD + /; (n159v)/i + ], [MODEL, [VENDOR, 'HMD'], [TYPE, MOBILE]], [ + // MIXED /(imo) (tab \w+)/i, // IMO - /(infinix) (x1101b?)/i // Infinix XPad + /(infinix|tecno) (x1101b?|p904|dp(7c|8d|10a)( pro)?|p70[1-3]a?|p904|t1101)/i // Infinix XPad / Tecno ], [VENDOR, MODEL, [TYPE, TABLET]], [ - /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus(?! zenw)|dell|jolla|meizu|motorola|polytron|infinix|tecno|micromax|advan)[-_ ]?([-\w]*)/i, - // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron/Infinix/Tecno/Micromax/Advan - /; (blu|hmd|imo|tcl)[_ ]([\w\+ ]+?)(?: bui|\)|; r)/i, // BLU/HMD/IMO/TCL + /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus(?! zenw)|dell|jolla|meizu|motorola|polytron|tecno|micromax|advan)[-_ ]?([-\w]*)/i, + // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron/Tecno/Micromax/Advan + /; (blu|hmd|imo|infinix|lava|oneplus|tcl)[_ ]([\w\+ ]+?)(?: bui|\)|; r)/i, // BLU/HMD/IMO/Infinix/Lava/OnePlus/TCL /(hp) ([\w ]+\w)/i, // HP iPAQ /(microsoft); (lumia[\w ]+)/i, // Microsoft Lumia - /(lenovo)[-_ ]?([-\w ]+?)(?: bui|\)|\/)/i, // Lenovo /(oppo) ?([\w ]+) bui/i // OPPO ], [VENDOR, MODEL, [TYPE, MOBILE]], [ @@ -768,6 +801,7 @@ ], [VENDOR, [TYPE, SMARTTV]], [ /hbbtv.+maple;(\d+)/i ], [[MODEL, /^/, 'SmartTV'], [VENDOR, SAMSUNG], [TYPE, SMARTTV]], [ + /(vizio)(?: |.+model\/)(\w+-\w+)/i, // Vizio /tcast.+(lg)e?. ([-\w]+)/i // LG SmartTV ], [VENDOR, MODEL, [TYPE, SMARTTV]], [ /(nux; netcast.+smarttv|lg (netcast\.tv-201\d|android tv))/i @@ -799,26 +833,27 @@ ], [VENDOR, MODEL, [TYPE, SMARTTV]], [ /\b(roku)[\dx]*[\)\/]((?:dvp-)?[\d\.]*)/i, // Roku /hbbtv\/\d+\.\d+\.\d+ +\([\w\+ ]*; *([\w\d][^;]*);([^;]*)/i // HbbTV devices - ], [[VENDOR, trim], [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:)\b/i + /\b(android tv|smart[- ]?tv|opera tv|tv; rv:|large screen[\w ]+safari)\b/i ], [[TYPE, SMARTTV]], [ /////////////////// // CONSOLES /////////////////// - /(ouya)/i, // Ouya - /(nintendo) (\w+)/i // Nintendo - ], [VENDOR, MODEL, [TYPE, CONSOLE]], [ - /droid.+; (shield)( bui|\))/i // Nvidia Portable - ], [MODEL, [VENDOR, NVIDIA], [TYPE, CONSOLE]], [ /(playstation \w+)/i // Playstation ], [MODEL, [VENDOR, SONY], [TYPE, CONSOLE]], [ /\b(xbox(?: one)?(?!; xbox))[\); ]/i // Microsoft Xbox ], [MODEL, [VENDOR, MICROSOFT], [TYPE, CONSOLE]], [ + /(ouya)/i, // Ouya + /(nintendo) (\w+)/i, // Nintendo + /(retroid) (pocket ([^\)]+))/i // Retroid Pocket + ], [VENDOR, MODEL, [TYPE, CONSOLE]], [ + /droid.+; (shield)( bui|\))/i // Nvidia Portable + ], [MODEL, [VENDOR, NVIDIA], [TYPE, CONSOLE]], [ /////////////////// // WEARABLES @@ -854,6 +889,8 @@ ], [VENDOR, MODEL, [TYPE, XR]], [ /(quest( \d| pro)?s?).+vr/i // Meta Quest ], [MODEL, [VENDOR, FACEBOOK], [TYPE, XR]], [ + /mobile vr; rv.+firefox/i // Unidentifiable VR device using Firefox Reality / Wolvic + ], [[TYPE, XR]], [ /////////////////// // EMBEDDED @@ -865,7 +902,7 @@ ], [MODEL, [VENDOR, AMAZON], [TYPE, EMBEDDED]], [ /(homepod).+mac os/i // Apple HomePod ], [MODEL, [VENDOR, APPLE], [TYPE, EMBEDDED]], [ - /windows iot/i + /windows iot/i // Unidentifiable embedded device using Windows IoT ], [[TYPE, EMBEDDED]], [ //////////////////// @@ -911,14 +948,17 @@ os : [[ // Windows - /microsoft (windows) (vista|xp)/i // Windows (iTunes) + /(windows nt) (6\.[23]); arm/i // Windows RT + ], [[NAME, /N/, 'R'], [VERSION, strMapper, windowsVersionMap]], [ + /(windows (?:phone|mobile|iot))(?: os)?[\/ ]?([\d\.]*( se)?)/i, // Windows IoT/Mobile/Phone + // Windows NT/3.1/95/98/ME/2000/XP/Vista/7/8/8.1/10/11 + /(windows)[\/ ](1[01]|2000|3\.1|7|8(\.1)?|9[58]|me|server 20\d\d( r2)?|vista|xp)/i + ], [NAME, VERSION], [ + /windows nt ?([\d\.\)]*)(?!.+xbox)/i, + /\bwin(?=3| ?9|n)(?:nt| 9x )?([\d\.;]*)/i + ], [[VERSION, /(;|\))/g, '', strMapper, windowsVersionMap], [NAME, WINDOWS]], [ + /(windows ce)\/?([\d\.]*)/i // Windows CE ], [NAME, VERSION], [ - /(windows (?:phone(?: os)?|mobile|iot))[\/ ]?([\d\.\w ]*)/i // Windows Phone - ], [NAME, [VERSION, strMapper, windowsVersionMap]], [ - /windows nt 6\.2; (arm)/i, // Windows RT - /windows[\/ ]([ntce\d\. ]+\w)(?!.+xbox)/i, - /(?:win(?=3|9|n)|win 9x )([nt\d\.]+)/i - ], [[VERSION, strMapper, windowsVersionMap], [NAME, WINDOWS]], [ // iOS/macOS /[adehimnop]{4,7}\b(?:.*os ([\w]+) like mac|; opera)/i, // iOS @@ -926,7 +966,7 @@ /cfnetwork\/.+darwin/i ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [ /(mac os x) ?([\w\. ]*)/i, - /(macintosh|mac_powerpc\b)(?!.+haiku)/i // Mac OS + /(macintosh|mac_powerpc\b)(?!.+(haiku|morphos))/i // Mac OS ], [[NAME, 'macOS'], [VERSION, /_/g, '.']], [ // Google Chromecast @@ -942,12 +982,13 @@ ], [VERSION, [NAME, CHROMECAST]], [ // Mobile OSes - /droid ([\w\.]+)\b.+(android[- ]x86|harmonyos)/i // Android-x86/HarmonyOS + /droid ([\w\.]+)\b.+(android[- ]x86)/i // Android-x86 ], [VERSION, NAME], [ /(ubuntu) ([\w\.]+) like android/i // Ubuntu Touch ], [[NAME, /(.+)/, '$1 Touch'], VERSION], [ + /(harmonyos)[\/ ]?([\d\.]*)/i, // HarmonyOS // Android/Blackberry/WebOS/QNX/Bada/RIM/KaiOS/Maemo/MeeGo/S40/Sailfish OS/OpenHarmony/Tizen - /(android|bada|blackberry|kaios|maemo|meego|openharmony|qnx|rim tablet os|sailfish|series40|symbian|tizen|webos)\w*[-\/\.; ]?([\d\.]*)/i + /(android|bada|blackberry|kaios|maemo|meego|openharmony|qnx|rim tablet os|sailfish|series40|symbian|tizen)\w*[-\/\.; ]?([\d\.]*)/i ], [NAME, VERSION], [ /\(bb(10);/i // BlackBerry 10 ], [VERSION, [NAME, BLACKBERRY]], [ @@ -955,9 +996,12 @@ ], [VERSION, [NAME, 'Symbian']], [ /mozilla\/[\d\.]+ \((?:mobile|tablet|tv|mobile; [\w ]+); rv:.+ gecko\/([\w\.]+)/i // Firefox OS ], [VERSION, [NAME, FIREFOX+' OS']], [ - /web0s;.+rt(tv)/i, - /\b(?:hp)?wos(?:browser)?\/([\w\.]+)/i // WebOS + /\b(?:hp)?wos(?:browser)?\/([\w\.]+)/i, // WebOS + /webos(?:[ \/]?|\.tv-20(?=2[2-9]))(\d[\d\.]*)/i ], [VERSION, [NAME, 'webOS']], [ + /web0s;.+?(?:chr[o0]me|safari)\/(\d+)/i + // https://webostv.developer.lge.com/develop/specifications/web-api-and-web-engine + ], [[VERSION, strMapper, {'25':'120','24':'108','23':'94','22':'87','6':'79','5':'68','4':'53','3':'38','2':'538','1':'537','*':'TV'}], [NAME, 'webOS']], [ /watch(?: ?os[,\/]|\d,\d\/)([\d\.]+)/i // watchOS ], [VERSION, [NAME, 'watchOS']], [ @@ -977,20 +1021,20 @@ // Other /\b(joli|palm)\b ?(?:os)?\/?([\w\.]*)/i, // Joli/Palm - /(mint)[\/\(\) ]?(\w*)/i, // Mint - /(mageia|vectorlinux)[; ]/i, // Mageia/VectorLinux - /([kxln]?ubuntu|debian|suse|opensuse|gentoo|arch(?= linux)|slackware|fedora|mandriva|centos|pclinuxos|red ?hat|zenwalk|linpus|raspbian|plan 9|minix|risc os|contiki|deepin|manjaro|elementary os|sabayon|linspire)(?: gnu\/linux)?(?: enterprise)?(?:[- ]linux)?(?:-gnu)?[-\/ ]?(?!chrom|package)([-\w\.]*)/i, - // Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware/Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus/Raspbian/Plan9/Minix/RISCOS/Contiki/Deepin/Manjaro/elementary/Sabayon/Linspire - /(hurd|linux)(?: arm\w*| x86\w*| ?)([\w\.]*)/i, // Hurd/Linux + /linux.+(mint)[\/\(\) ]?([\w\.]*)/i, // Mint + /(mageia|vectorlinux|fuchsia|arcaos|arch(?= ?linux))[;l ]([\d\.]*)/i, // Mageia/VectorLinux/Fuchsia/ArcaOS/Arch + /([kxln]?ubuntu|debian|suse|opensuse|gentoo|slackware|fedora|mandriva|centos|pclinuxos|red ?hat|zenwalk|linpus|raspbian|plan 9|minix|risc os|contiki|deepin|manjaro|elementary os|sabayon|linspire|knoppix)(?: gnu[\/ ]linux)?(?: enterprise)?(?:[- ]linux)?(?:-gnu)?[-\/ ]?(?!chrom|package)([-\w\.]*)/i, + // Ubuntu/Debian/SUSE/Gentoo/Slackware/Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus/Raspbian/Plan9/Minix/RISCOS/Contiki/Deepin/Manjaro/elementary/Sabayon/Linspire/Knoppix + /((?:open)?solaris)[-\/ ]?([\w\.]*)/i, // Solaris + /\b(aix)[; ]([1-9\.]{0,4})/i, // AIX + /(hurd|linux|morphos)(?: (?:arm|x86|ppc)\w*| ?)([\w\.]*)/i, // Hurd/Linux/MorphOS /(gnu) ?([\w\.]*)/i, // GNU /\b([-frentopcghs]{0,5}bsd|dragonfly)[\/ ]?(?!amd|[ix346]{1,2}86)([\w\.]*)/i, // FreeBSD/NetBSD/OpenBSD/PC-BSD/GhostBSD/DragonFly - /(haiku) (\w+)/i // Haiku + /(haiku) ?(r\d)?/i // Haiku ], [NAME, VERSION], [ - /(sunos) ?([\w\.\d]*)/i // Solaris + /(sunos) ?([\d\.]*)/i // Solaris ], [[NAME, 'Solaris'], VERSION], [ - /((?:open)?solaris)[-\/ ]?([\w\.]*)/i, // Solaris - /(aix) ((\d)(?=\.|\)| )[\w\.])*/i, // AIX - /\b(beos|os\/2|amigaos|morphos|openvms|fuchsia|hp-ux|serenityos)/i, // BeOS/OS2/AmigaOS/MorphOS/OpenVMS/Fuchsia/HP-UX/SerenityOS + /\b(beos|os\/2|amigaos|openvms|hp-ux|serenityos)/i, // BeOS/OS2/AmigaOS/OpenVMS/HP-UX/SerenityOS /(unix) ?([\w\.]*)/i // UNIX ], [NAME, VERSION] ] @@ -1224,21 +1268,20 @@ for (var i in brands) { var brandName = brands[i].brand || brands[i], brandVersion = brands[i].version; - if (this.itemType == UA_BROWSER && !/not.a.brand/i.test(brandName) && (!prevName || (/chrom/i.test(prevName) && brandName != CHROMIUM))) { - brandName = strMapper(brandName, { - 'Chrome' : 'Google Chrome', - 'Edge' : 'Microsoft Edge', - 'Chrome WebView' : 'Android WebView', - 'Chrome Headless' : 'HeadlessChrome', - 'Huawei Browser' : 'HuaweiBrowser', - 'MIUI Browser' : 'Miui Browser', - 'Opera Mobi' : 'OperaMobile', - 'Yandex' : 'YaBrowser' - }); - this.set(NAME, brandName) - .set(VERSION, brandVersion) - .set(MAJOR, majorize(brandVersion)); - prevName = brandName; + if (this.itemType == UA_BROWSER && + !/not.a.brand/i.test(brandName) && + (!prevName || + (/Chrom/.test(prevName) && brandName != CHROMIUM) || + (prevName == EDGE && /WebView2/.test(brandName)) + )) { + brandName = strMapper(brandName, browserHintsMap); + prevName = this.get(NAME); + if (!(prevName && !/Chrom/.test(prevName) && /Chrom/.test(brandName))) { + this.set(NAME, brandName) + .set(VERSION, brandVersion) + .set(MAJOR, majorize(brandVersion)); + } + prevName = brandName; } if (this.itemType == UA_ENGINE && brandName == CHROMIUM) { this.set(VERSION, brandVersion); diff --git a/test/data/ua/browser/browser-all.json b/test/data/ua/browser/browser-all.json index 3fc0e5e..9f39de9 100644 --- a/test/data/ua/browser/browser-all.json +++ b/test/data/ua/browser/browser-all.json @@ -2229,6 +2229,26 @@ "major" : "74" } }, + { + "desc" : "Microsoft Edge WebView", + "ua" : "Mozilla/5.0 (Windows IoT 10.0; Android 6.0.1; WebView/3.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Mobile Safari/537.36 Edge/18.17763", + "expect" : + { + "name" : "Edge WebView", + "version" : "18.17763", + "major" : "18" + } + }, + { + "desc" : "Microsoft Edge WebView2", + "ua" : "Mozilla/5.0 (Linux; Android 11; SM-G991B Build/RP1A.200720.012; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/91.0.4472.120 Mobile Safari/537.36 EdgW/1.0", + "expect" : + { + "name" : "Edge WebView2", + "version" : "91.0.4472.120", + "major" : "91" + } + }, { "desc" : "Iridium", "ua" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Iridium/43.8 Safari/537.36 Chrome/43.0.2357.132", diff --git a/test/data/ua/device/_others.json b/test/data/ua/device/_others.json index c47da24..55329b3 100644 --- a/test/data/ua/device/_others.json +++ b/test/data/ua/device/_others.json @@ -122,15 +122,6 @@ "type": "undefined" } }, - { - "desc": "OnePlus 7T Pro", - "ua": "Mozilla/5.0 (Linux; Android 10; HD1913) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.5563.57 Mobile Safari/537.36 EdgA/110.0.1587.66", - "expect": { - "vendor": "undefined", - "model": "HD1913", - "type": "mobile" - } - }, { "desc": "Philips SmartTV", "ua": "Opera/9.80 HbbTV/1.1.1 (; Philips; ; ; ; ) NETTV/4.0.2; en) Version/11.60", @@ -281,6 +272,69 @@ "type": "smarttv" } }, + { + "desc": "Unknown TV", + "ua": "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.127 Large Screen Safari/533.4 GoogleTV/ 162671", + "expect": { + "vendor": "undefined", + "model": "undefined", + "type": "smarttv" + } + }, + { + "desc": "Unknown TV", + "ua": "Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.41 (KHTML, like Gecko) Large Screen WebAppManager Safari/537.41", + "expect": { + "vendor": "undefined", + "model": "undefined", + "type": "smarttv" + } + }, + { + "desc": "Unknown VR Device using Firefox Reality", + "ua": "Mozilla/5.0 (Android 10; Mobile VR; rv:123.0) Gecko/123.0 Firefox/123.0", + "expect": { + "vendor": "undefined", + "model": "undefined", + "type": "xr" + } + }, + { + "desc": "Unknown VR Device using Wolvic", + "ua": "Mozilla/5.0 (Android 14; Mobile VR; rv:128.0) Gecko/128.0 Firefox/128.0 Wolvic/1.8", + "expect": { + "vendor": "undefined", + "model": "undefined", + "type": "xr" + } + }, + { + "desc": "Smart TV", + "ua": "Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 HbbTV/1.6.1 ( DRM; LGE/ATMACA/GRAETZ; GR32S1470; WEBOS22 04.41.53; W22_K8AP; DTV_C22L;) LaTivu_1.0.1_2022", + "expect": { + "vendor": "GRAETZ", + "model": "GR32S1470", + "type": "smarttv" + } + }, + { + "desc": "Smart TV", + "ua": "Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36 HbbTV/1.5.1 (+DRM; LGE/DUALSHINE/SKYTECH; ST-5090; WEBOS5.0 04.50.63; W50_K6LP; DTV_C20P;)", + "expect": { + "vendor": "SKYTECH", + "model": "ST-5090", + "type": "smarttv" + } + }, + { + "desc": "Smart TV", + "ua": "Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 HbbTV/1.6.1 (+DRM; LGE/SILICONPLAYER/Hyundai; 50HYN3205; WEBOS22 04.42.26; W22_K8LP; DTV_C22P;)", + "expect": { + "vendor": "Hyundai", + "model": "50HYN3205", + "type": "smarttv" + } + }, { "desc": "PDA with Windows CE", "ua": "Mozilla/4.0 (PDA; Windows CE/1.0.1) NetFront/3.0", diff --git a/test/data/ua/device/google.json b/test/data/ua/device/google.json index a06b991..0897534 100644 --- a/test/data/ua/device/google.json +++ b/test/data/ua/device/google.json @@ -71,51 +71,6 @@ "type": "mobile" } }, - { - "desc": "Google Pixel Tablet", - "ua": "Mozilla/5.0 (Linux; Android 14; Pixel Tablet Build/AP2A.240905.003; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.107 Safari/537.36", - "expect": { - "vendor": "Google", - "model": "Pixel Tablet", - "type": "tablet" - } - }, - { - "desc": "Google Pixel Watch", - "ua": "Dalvik/2.1.0 (Linux; U; Android 13; Google Pixel Watch Build/TWD4.231005.002)", - "expect": { - "vendor": "Google", - "model": "Pixel Watch", - "type": "wearable" - } - }, - { - "desc": "Google Pixel Watch 2", - "ua": "Dalvik/2.1.0 (Linux; U; Android 13; Google Pixel Watch 2 Build/TWD9.240605.001.A1)", - "expect": { - "vendor": "Google", - "model": "Pixel Watch 2", - "type": "wearable" - } - }, - { - "desc": "Google Pixel XL", - "ua": "Mozilla/5.0 (Linux; Android 7.1; Pixel XL Build/NDE63X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.85 Mobile Safari/537.36", - "expect": { - "vendor": "Google", - "model": "Pixel XL", - "type": "mobile" - } - }, - { - "desc": "Google Pixel XL", - "ua": "Mozilla/5.0 (Linux; Android 9; Pixel XL) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Mobile Safari/537.36", - "expect": { - "vendor": "Google", - "model": "Pixel XL", - "type": "mobile" - } - }, { "desc": "Google Pixel 2", "ua": "Mozilla/5.0 (Linux; Android 8.1.0; Pixel 2 Build/OPM1.171019.013) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.111 Safari/537.36", @@ -125,6 +80,24 @@ "type": "mobile" } }, + { + "desc": "Google Pixel 2", + "ua": "Mozilla/5.0 (Linux; Android 10; Pixel 2) AppleWebKit/537.36 (KHTML, like Gecko) Edg/57.0.986.6", + "expect": { + "vendor": "Google", + "model": "Pixel 2", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 2", + "ua": "Mozilla/5.0 (Linux; Android 7.1.2; G011A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.88 Safari/537.36 OPR/68.3.3557.64528", + "expect": { + "vendor": "Google", + "model": "G011A", + "type": "mobile" + } + }, { "desc": "Google Pixel 2 XL", "ua": "Mozilla/5.0 (Linux; Android 8.1.0; Pixel 2 XL Build/OPM1.171019.013) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.111 Safari/537.36", @@ -152,6 +125,24 @@ "type": "mobile" } }, + { + "desc": "Google Pixel 3", + "ua": "Mozilla/5.0 (Linux; Android 11; G013A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "G013A", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 3a", + "ua": "Mozilla/5.0 (Linux; Android 14; G020E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "G020E", + "type": "mobile" + } + }, { "desc": "Google Pixel 3 XL", "ua": "Mozilla/5.0 (Linux; Android 9; Pixel 3 XL Build/PD1A.180720.030) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36", @@ -197,6 +188,15 @@ "type": "mobile" } }, + { + "desc": "Google Pixel 4", + "ua": "Mozilla/5.0 (Linux; Android 12; G020M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "G020M", + "type": "mobile" + } + }, { "desc": "Google Pixel 4a", "ua": "Mozilla/5.0 (Linux; Android 10; Pixel 4a) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.83 Mobile Safari/537.36", @@ -206,6 +206,42 @@ "type": "mobile" } }, + { + "desc": "Google Pixel 4a", + "ua": "Mozilla/5.0 (Linux; Android 13; G025J) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "G025J", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 4a", + "ua": "Mozilla/5.0 (Linux; Android 12; GA02099) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "GA02099", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 4a", + "ua": "Mozilla/5.0 (Linux; Android 13; G025N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "G025N", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 4a (5G)", + "ua": "Mozilla/5.0 (Linux; Android 14; Pixel 4a (5G) Build/UP1A.231105.001.B2; ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Mobile Safari/537.36 EdgA/124.0.2478.64", + "expect": { + "vendor": "Google", + "model": "Pixel 4a (5G)", + "type": "mobile" + } + }, { "desc": "Google Pixel 4 XL", "ua": "Mozilla/5.0 (Linux; Android 10; Pixel 4 XL) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Mobile Safari/537.36", @@ -215,6 +251,33 @@ "type": "mobile" } }, + { + "desc": "Google Pixel 5", + "ua": "Mozilla/5.0 (Linux; Android 13; G5NZ6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "G5NZ6", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 5", + "ua": "Mozilla/5.0 (Linux; Android 12; GD1YQ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "GD1YQ", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 5", + "ua": "Mozilla/5.0 (Linux; Android 12; GTT9Q) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "GTT9Q", + "type": "mobile" + } + }, { "desc": "Google Pixel 5", "ua": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.120 Mobile Safari/537.36", @@ -224,6 +287,51 @@ "type": "mobile" } }, + { + "desc": "Google Pixel 5a 5G", + "ua": "Mozilla/5.0 (Linux; Android 14; G4S1M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "G4S1M", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 5a 5G", + "ua": "Mozilla/5.0 (Linux; Android 12; G1F8F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "G1F8F", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 6", + "ua": "Mozilla/5.0 (Linux; Android 11; Pixel 6 Build/QP1A.190711.020) AppleWebKit/545.31 (KHTML, like Gecko) Firefox/109.0.2318.118 Mobile Safari/545.22", + "expect": { + "vendor": "Google", + "model": "Pixel 6", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 6 Pro", + "ua": "Mozilla/5.0 (Linux; Android 15; Pixel 6 Pro Build/AP4A.241205.013; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/132.0.6834.163 Mobile Safari/537.36 Line/15.0.0/IAB", + "expect": { + "vendor": "Google", + "model": "Pixel 6 Pro", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 6 Pro", + "ua": "Mozilla/5.0 (Linux; Android 13; G8VOU) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "G8VOU", + "type": "mobile" + } + }, { "desc": "Google Pixel 7", "ua": "Mozilla/5.0 (Linux; Android 13; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36", @@ -232,5 +340,275 @@ "model": "Pixel 7", "type": "mobile" } + }, + { + "desc": "Google Pixel 7 Pro", + "ua": "Mozilla/5.0 (Linux; Android 15; Pixel 7 Pro Build/AP4A.250205.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/133.0.6943.121 Mobile Safari/537.36 musical_ly_2023808030 BytedanceWebview/d8a21c6", + "expect": { + "vendor": "Google", + "model": "Pixel 7 Pro", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 7 Pro", + "ua": "Mozilla/5.0 (Linux; Android 14; GP4BC) AppleWebKit/537.46 (KHTML, like Gecko) Chrome/118.0.5993.80 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "GP4BC", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 7 Pro", + "ua": "Mozilla/5.0 (Linux; Android 14; GE2AE) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.5993.48 Mobile Safari/537.46", + "expect": { + "vendor": "Google", + "model": "GE2AE", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 7a", + "ua": "Mozilla/5.0 (Linux; Android 14; Pixel 7a Build/AP2A.240905.003; ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Mobile Safari/537.36 EdgA/124.0.2478.64", + "expect": { + "vendor": "Google", + "model": "Pixel 7a", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 8", + "ua": "Mozilla/5.0 (Linux; Android 14; Pixel 8 Build/UPB2.230407.014) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.2.7822.95 Mobile Safari/537.36 Vivaldi/5.2.9076.131", + "expect": { + "vendor": "Google", + "model": "Pixel 8", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 8", + "ua": "Mozilla/5.0 (Linux; Android 14; Pixel 8 Pro Build/UPB1.230309.017; Rooted) AppleWebKit/537.36 (KHTML, like Gecko) Puffin/10.9.0 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "Pixel 8 Pro", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 8a", + "ua": "Mozilla/5.0 (Linux; Android 14; Google Pixel 8a) Chrome/121.0.6167 Mobile", + "expect": { + "vendor": "Google", + "model": "Pixel 8a", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 8a", + "ua": "Mozilla/5.0 (Linux; Android 15; GKV4X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "GKV4X", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 8a", + "ua": "Mozilla/5.0 (Linux; Android 15; G8HHN) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "G8HHN", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 8a", + "ua": "Mozilla/5.0 (Linux; Android 15; G576D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "G576D", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 9", + "ua": "Mozilla/5.0 (Linux; U; Android 14; Pixel 9) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.119 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "Pixel 9", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 9", + "ua": "Mozilla/5.0 (Linux; Android 15; G2YBB) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "G2YBB", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 9", + "ua": "Mozilla/5.0 (Linux; Android 15; GUR25) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "GUR25", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 9", + "ua": "Mozilla/5.0 (Linux; Android 15; GWVK6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "GWVK6", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 9", + "ua": "Mozilla/5.0 (Linux; Android 15; G1B60) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "G1B60", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 9 Pro", + "ua": "Mozilla/5.0 (Linux; Android 14; Pixel 9 Pro Build/AD1A.240530.047; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/134.0.6998.170 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/506.1.0.74.27;IABMV/1;]", + "expect": { + "vendor": "Google", + "model": "Pixel 9 Pro", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 9 Pro", + "ua": "Mozilla/5.0 (Linux; Android 15; GR83Y) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "GR83Y", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 9 Pro", + "ua": "Mozilla/5.0 (Linux; Android 15; GEC77) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "GEC77", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 9 Pro Fold", + "ua": "Mozilla/5.0 (Linux; Android 14; Pixel 9 Pro Fold) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "Pixel 9 Pro Fold", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 9 Pro Fold", + "ua": "Mozilla/5.0 (Linux; Android 15; GC15S) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "GC15S", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 9 Pro Fold", + "ua": "Mozilla/5.0 (Linux; Android 15; GGH2X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "GGH2X", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 9 Pro XL", + "ua": "Mozilla/5.0 (Linux; U; Android 15; Pixel 9 Pro XL Build/AP4A.250105.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/133.0.6943.89 Mobile Safari/537.36 OPR/88.0.2254.75874", + "expect": { + "vendor": "Google", + "model": "Pixel 9 Pro XL", + "type": "mobile" + } + }, + { + "desc": "Google Pixel Fold", + "ua": "Mozilla/5.0 (Linux; Android 15; Pixel Fold Build/AP4A.250105.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/132.0.6834.97 Safari/537.36 [FB_IAB/FB4A;FBAV/497.0.0.40.36;IABMV/1;]", + "expect": { + "vendor": "Google", + "model": "Pixel Fold", + "type": "mobile" + } + }, + { + "desc": "Google Pixel Tablet", + "ua": "Mozilla/5.0 (Linux; Android 14; Pixel Tablet Build/AP2A.240905.003; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.107 Safari/537.36", + "expect": { + "vendor": "Google", + "model": "Pixel Tablet", + "type": "tablet" + } + }, + { + "desc": "Google Pixel Watch", + "ua": "Dalvik/2.1.0 (Linux; U; Android 13; Google Pixel Watch Build/TWD4.231005.002)", + "expect": { + "vendor": "Google", + "model": "Pixel Watch", + "type": "wearable" + } + }, + { + "desc": "Google Pixel Watch 2", + "ua": "Dalvik/2.1.0 (Linux; U; Android 13; Google Pixel Watch 2 Build/TWD9.240605.001.A1)", + "expect": { + "vendor": "Google", + "model": "Pixel Watch 2", + "type": "wearable" + } + }, + { + "desc": "Google Pixel XL", + "ua": "Mozilla/5.0 (Linux; Android 7.1; Pixel XL Build/NDE63X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.85 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "Pixel XL", + "type": "mobile" + } + }, + { + "desc": "Google Pixel XL", + "ua": "Mozilla/5.0 (Linux; Android 9; Pixel XL) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "Pixel XL", + "type": "mobile" + } + }, + { + "desc": "Google Pixelbook", + "ua": "Mozilla/5.0 (Linux; Android 9; Google Pixelbook) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36", + "expect": { + "vendor": "Google", + "model": "Pixelbook", + "type": "undefined" + } + }, + { + "desc": "Google Pixelbook Go", + "ua": "Mozilla/5.0 (Linux; Android 9; Google Pixelbook Go) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36 OPR/62.3.3146.57763", + "expect": { + "vendor": "Google", + "model": "Pixelbook Go", + "type": "undefined" + } } ] \ No newline at end of file diff --git a/test/data/ua/device/hmd.json b/test/data/ua/device/hmd.json index a7d38e2..037148c 100644 --- a/test/data/ua/device/hmd.json +++ b/test/data/ua/device/hmd.json @@ -8,6 +8,15 @@ "type": "mobile" } }, + { + "desc": "HMD Fusion", + "ua": "Mozilla/5.0 (Linux; Android 14; HMD Fusion) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "HMD", + "model": "Fusion", + "type": "mobile" + } + }, { "desc": "HMD Pulse", "ua": "Mozilla/5.0 (Linux; Android 14; HMD Pulse) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Mobile Safari/537.36", @@ -34,5 +43,23 @@ "model": "Pulse Pro", "type": "mobile" } + }, + { + "desc": "HMD Skyline", + "ua": "Mozilla/5.0 (Linux; arm_64; Android 14; HMD Skyline) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.1804 YaApp_Android/24.120.1 YaSearchBrowser/24.120.1 BroPP/1.0 SA/3 Mobile Safari/537.36", + "expect": { + "vendor": "HMD", + "model": "Skyline", + "type": "mobile" + } + }, + { + "desc": "HMD Vibe", + "ua": "Mozilla/5.0 (Linux; Android 14; N159V Build/UKQ1.231025.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/135.0.7049.111 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/497.0.0.47.36;]", + "expect": { + "vendor": "HMD", + "model": "N159V", + "type": "mobile" + } } ] \ No newline at end of file diff --git a/test/data/ua/device/infinix.json b/test/data/ua/device/infinix.json index 6c356d3..3474003 100644 --- a/test/data/ua/device/infinix.json +++ b/test/data/ua/device/infinix.json @@ -1,4 +1,22 @@ [ + { + "desc": "Infinix Hot 4", + "ua": "Mozilla/5.0 (Linux; U; Android 7.0; en-us; Infinix HOT 4 Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36 PHX/17.9", + "expect": { + "vendor": "Infinix", + "model": "HOT 4", + "type": "mobile" + } + }, + { + "desc": "Infinix Hot 4 Pro", + "ua": "Mozilla/5.0 (Linux; Android 6.0; Infinix_X556_LTE Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/69.0.3497.100 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/390.0.0.27.105;]", + "expect": { + "vendor": "Infinix", + "model": "X556_LTE", + "type": "mobile" + } + }, { "desc": "Infinix Hot 7 Pro", "ua": "Mozilla/5.0 (Linux; Android 9; Infinix X625C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36", @@ -26,6 +44,15 @@ "type": "mobile" } }, + { + "desc": "Infinix Note 3", + "ua": "Mozilla/5.0 (Linux; Android 6.0; Infinix_X601_LTE Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/81.0.4044.111 Mobile Safari/537.36 GSA/11.5.9.21.arm64", + "expect": { + "vendor": "Infinix", + "model": "X601_LTE", + "type": "mobile" + } + }, { "desc": "Infinix Smart 5", "ua": "Mozilla/5.0 (Linux; Android 10; Infinix X657C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Mobile Safari/537.36", diff --git a/test/data/ua/device/lava.json b/test/data/ua/device/lava.json new file mode 100644 index 0000000..5279f2c --- /dev/null +++ b/test/data/ua/device/lava.json @@ -0,0 +1,110 @@ +[ + { + "desc": "Lava Agni 2 5G", + "ua": "Mozilla/5.0 (Linux; Android 14; LAVA LXX504 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/133.0.6943.46 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/499.0.0.31.60;IABMV/1;]", + "expect": { + "vendor": "LAVA", + "model": "LXX504", + "type": "mobile" + } + }, + { + "desc": "Lava Agni 5G", + "ua": "Mozilla/5.0 (Linux; Android 12; LAVA LXX501 Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/122.0.6261.119 Mobile Safari/537.36[FBAN/EMA;FBLC/hi_IN;FBAV/396.0.0.9.115;]", + "expect": { + "vendor": "LAVA", + "model": "LXX501", + "type": "mobile" + } + }, + { + "desc": "Lava Blaze", + "ua": "Mozilla/5.0 (Linux; U; Android 12; en-US; LAVA Blaze Build/SP1A.210812.016) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 UCBrowser/13.4.0.1306 Mobile Safari/537.36", + "expect": { + "vendor": "LAVA", + "model": "Blaze", + "type": "mobile" + } + }, + { + "desc": "Lava Blaze 2", + "ua": "Mozilla/5.0 (Linux; Android 13; LAVA LZX409 Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/132.0.6834.97 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/497.0.0.47.36;IABMV/1;]", + "expect": { + "vendor": "LAVA", + "model": "LZX409", + "type": "mobile" + } + }, + { + "desc": "Lava Blaze 5G", + "ua": "Mozilla/5.0 (Linux; Android 12; LAVA LXX503) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/23.0 Chrome/115.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "LAVA", + "model": "LXX503", + "type": "mobile" + } + }, + { + "desc": "Lava Blaze Curve", + "ua": "Mozilla/5.0 (Linux; Android 14; LAVA LXX505 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/134.0.6998.105 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/505.0.0.57.45;IABMV/1;]", + "expect": { + "vendor": "LAVA", + "model": "LXX505", + "type": "mobile" + } + }, + { + "desc": "Lava Blaze Pro", + "ua": "Mozilla/5.0 (Linux; Android 13; LAVA LZX404 Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/134.0.6998.50 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/503.0.0.69.76;IABMV/1;]", + "expect": { + "vendor": "LAVA", + "model": "LZX404", + "type": "mobile" + } + }, + { + "desc": "Lava Iris 46", + "ua": "Mozilla/5.0 (Linux; Android 9; LAVA LH9950) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/21.0 Chrome/110.0.5481.154 Mobile Safari/537.36", + "expect": { + "vendor": "LAVA", + "model": "LH9950", + "type": "mobile" + } + }, + { + "desc": "Lava Iris 54", + "ua": "Mozilla/5.0 (Linux; U; Android 9; LAVA LH9931 Build/PPR1.180610.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/79.0.3945.116 Mobile Safari/537.36 OPR/39.1.2254.136708", + "expect": { + "vendor": "LAVA", + "model": "LH9931", + "type": "mobile" + } + }, + { + "desc": "Lava Storm 5G", + "ua": "Mozilla/5.0 (Linux; Android 13; LAVA LXX508 Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/129.0.6668.100 Mobile Safari/537.36", + "expect": { + "vendor": "LAVA", + "model": "LXX508", + "type": "mobile" + } + }, + { + "desc": "Lava V7 Prime", + "ua": "Mozilla/5.0 (Linux; Android 9; LAVA LE9940) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Mobile Safari/537.36", + "expect": { + "vendor": "LAVA", + "model": "LE9940", + "type": "mobile" + } + }, + { + "desc": "Lava V7s Prime", + "ua": "Mozilla/5.0 (Linux; U; Android 9; LAVA LE9940_W Build/PPR1.180610.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/79.0.3945.116 Mobile Safari/537.36 OPR/43.2.2254.140294", + "expect": { + "vendor": "LAVA", + "model": "LE9940_W", + "type": "mobile" + } + } +] \ No newline at end of file diff --git a/test/data/ua/device/lg.json b/test/data/ua/device/lg.json index 9d63ac1..9f125d7 100644 --- a/test/data/ua/device/lg.json +++ b/test/data/ua/device/lg.json @@ -143,6 +143,24 @@ "type": "smarttv" } }, + { + "desc": "LG Smart TV", + "ua": "Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chr0me/53.0.2785.34 Safari/537.36 LG Browser/8.00.00(LGE; 32LM627BPSB; 05.40.45; 1; DTV_W19R); webOS.TV-2019; LG NetCast.TV-2013 Compatible (LGE, 32LM627BPSB, wireless)", + "expect": { + "vendor": "LG", + "model": "32LM627BPSB", + "type": "smarttv" + } + }, + { + "desc": "LG Smart TV", + "ua": "Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 HbbTV/1.3.1 ( DRM; LGE; OLED55B7V_Z; WEBOS3.5 06.10.60; W3_M16P; ) FVC/2.0 (LGE; WEBOS3.5 ;)", + "expect": { + "vendor": "LG", + "model": "OLED55B7V_Z", + "type": "smarttv" + } + }, { "desc": "LG Android TV", "ua": "Mozilla/5.0 (Linux; U; Android 4.2.2; zh-cn; LG Android TV Build/JDQ39) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30", diff --git a/test/data/ua/device/motorola.json b/test/data/ua/device/motorola.json index b9227ba..18d1e48 100644 --- a/test/data/ua/device/motorola.json +++ b/test/data/ua/device/motorola.json @@ -1,28 +1,10 @@ [ { - "desc": "Motorola Moto X", - "ua": "Mozilla/5.0 (Linux; Android 4.4.4; XT1097 Build/KXE21.187-38) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.109 Mobile Safari/537.36", + "desc": "Motorola Defy XT", + "ua": "Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; XT555C Build/V1.67D) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", "expect": { "vendor": "Motorola", - "model": "XT1097", - "type": "mobile" - } - }, - { - "desc": "Motorola Moto Z3 Play", - "ua": "Mozilla/5.0 (Linux; Android 9; Moto Z3 Play) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36", - "expect": { - "vendor": "Motorola", - "model": "Moto Z3 Play", - "type": "mobile" - } - }, - { - "desc": "Motorola Nexus 6", - "ua": "Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.20 Mobile Safari/537.36", - "expect": { - "vendor": "Motorola", - "model": "Nexus 6", + "model": "XT555C", "type": "mobile" } }, @@ -35,6 +17,42 @@ "type": "mobile" } }, + { + "desc": "Motorola Edge 30 Pro", + "ua": "Mozilla/5.0 (Linux; Android 13; XT2201-1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Motorola", + "model": "XT2201-1", + "type": "mobile" + } + }, + { + "desc": "Motorola Edge 30 Ultra", + "ua": "Mozilla/5.0 (Linux; Android 14; motorola edge 30 ultra Build/U1SQS34.52-21-1-13; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.107 M", + "expect": { + "vendor": "Motorola", + "model": "edge 30 ultra", + "type": "mobile" + } + }, + { + "desc": "Motorola Edge 40", + "ua": "Mozilla/5.0 (Linux; Android 14; motorola edge 40 Build/U1TL34.115-16-1-7; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.104 Mobile Safari/537.36", + "expect": { + "vendor": "Motorola", + "model": "edge 40", + "type": "mobile" + } + }, + { + "desc": "Motorola Edge X30", + "ua": "Mozilla/5.0 (Linux; Android 14; XT2201-2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.59 Mobile Safari/537.36", + "expect": { + "vendor": "Motorola", + "model": "XT2201-2", + "type": "mobile" + } + }, { "desc": "Motorola RAZR 2019", "ua": "Mozilla/5.0 (Linux; Android 9; motorola razr) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/11.1 Chrome/75.0.3770.143 Mobile Safari/537.36", @@ -45,11 +63,65 @@ } }, { - "desc": "Moto X", - "ua": "Mozilla/5.0 (Linux; U; Android 4.2; xx-xx; XT1058 Build/13.9.0Q2.X-70-GHOST-ATT_LE-2) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", + "desc": "Motorola Moto 360", + "ua": "Mozilla/5.0 (Linux; Android 4.4; Moto 360 Build/KNX01S) AppleWebKit/537.36 (KHTML, like Gecko) WIB/0.9.8 Mobile Safari/537.36", "expect": { "vendor": "Motorola", - "model": "XT1058", + "model": "Moto 360", + "type": "wearable" + } + }, + { + "desc": "Motorola Moto E", + "ua": "Mozilla/5.0 (Linux; Android 7.1.1; Moto E (4) Build/NDQS26.69-64-11-7; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/56.0.2924.87 Mobile Safari/537.36", + "expect": { + "vendor": "Motorola", + "model": "Moto E (4)", + "type": "mobile" + } + }, + { + "desc": "Motorola Moto E6s", + "ua": "Mozilla/5.0 (Linux; Android 9; MOTOROLA E6S) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Motorola", + "model": "E6S", + "type": "mobile" + } + }, + { + "desc": "Motorola Moto E7 Plus", + "ua": "Mozilla/5.0 (Linux; Android 10; moto e(7) plus Build/QPZS30.30-Q3-38-69-12; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.14 Mobile Safari/537.36", + "expect": { + "vendor": "Motorola", + "model": "moto e(7) plus", + "type": "mobile" + } + }, + { + "desc": "Motorola Moto E7 Plus", + "ua": "Mozilla/5.0 (Linux; Android 14; XT2081-1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.5790.171 Mobile Safari/537.36 OPR/102.0.4864.0", + "expect": { + "vendor": "Motorola", + "model": "XT2081-1", + "type": "mobile" + } + }, + { + "desc": "Motorola Moto G 5G", + "ua": "Mozilla/5.0 (Linux; Android 14; moto g 5G - 2023 Build/U1TPNS34.26-48-2-7; ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Mobile Safari/537.36 EdgA/124.0.2478.64", + "expect": { + "vendor": "Motorola", + "model": "moto g 5G - 2023", + "type": "mobile" + } + }, + { + "desc": "Motorola Moto G 5G (2022)", + "ua": "Mozilla/5.0 (Linux; Android 12; moto g 5G (2022) Build/S1SAS32.47-77-9; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/111.0.5563.116 Mobile Safari/537.36 [FB_IAB/Orca-Android;FBAV/402.0.0.11.101;]", + "expect": { + "vendor": "Motorola", + "model": "moto g 5G (2022)", "type": "mobile" } }, @@ -72,21 +144,156 @@ } }, { - "desc": "Motorola Moto E", - "ua": "Mozilla/5.0 (Linux; Android 7.1.1; Moto E (4) Build/NDQS26.69-64-11-7; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/56.0.2924.87 Mobile Safari/537.36", + "desc": "Motorola Moto G10", + "ua": "Mozilla/5.0 (Linux; Android 12; XT2127-2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Mobile Safari/537.36", "expect": { "vendor": "Motorola", - "model": "Moto E (4)", + "model": "XT2127-2", "type": "mobile" } }, { - "desc": "Motorola Moto 360", - "ua": "Mozilla/5.0 (Linux; Android 4.4; Moto 360 Build/KNX01S) AppleWebKit/537.36 (KHTML, like Gecko) WIB/0.9.8 Mobile Safari/537.36", + "desc": "Motorola Moto G24 Power", + "ua": "Mozilla/5.0 (Linux; U; Android 14; moto g24 power Build/UTAS34.82-97-1; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/133.0.6943.138 Mobile Safari/537.36 OPR/89.0.2254.76420", "expect": { "vendor": "Motorola", - "model": "Moto 360", - "type": "wearable" + "model": "moto g24 power", + "type": "mobile" + } + }, + { + "desc": "Motorola Moto G30", + "ua": "Mozilla/5.0 (Linux; Android 14; XT2129-3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Motorola", + "model": "XT2129-3", + "type": "mobile" + } + }, + { + "desc": "Motorola Moto G54 5G", + "ua": "Mozilla/5.0 (Linux; Android 14; moto g54 5G Build/U1TDS34.94-12-9-10-2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.122 Mobile Safari/537.36 OPX/2", + "expect": { + "vendor": "Motorola", + "model": "moto g54 5G", + "type": "mobile" + } + }, + { + "desc": "Motorola Moto X", + "ua": "Mozilla/5.0 (Linux; Android 4.4.4; XT1097 Build/KXE21.187-38) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.109 Mobile Safari/537.36", + "expect": { + "vendor": "Motorola", + "model": "XT1097", + "type": "mobile" + } + }, + { + "desc": "Motorola Moto X", + "ua": "Mozilla/5.0 (Linux; U; Android 4.2; xx-xx; XT1058 Build/13.9.0Q2.X-70-GHOST-ATT_LE-2) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", + "expect": { + "vendor": "Motorola", + "model": "XT1058", + "type": "mobile" + } + }, + { + "desc": "Motorola Moto X Force", + "ua": "Mozilla/5.0 (Linux; U; Android 7.0; XT1580 Build/NPKS25.200-12-9; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/65.0.3325.109 Mobile Safari/537.36 OPR/32.0.2254.123747", + "expect": { + "vendor": "Motorola", + "model": "XT1580", + "type": "mobile" + } + }, + { + "desc": "Motorola Moto S30", + "ua": "Mozilla/5.0 (Linux; Android 13; XT2243-2 Build/T1SJC33.51-19-7; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/97.0.4692.98 Mobile Safari/537.36 T7/13.30 SP-engine/2.53.0 matrixstyle/0 lite baiduboxapp/6.2.0.10 (Baidu; P1 13) NABar/1.0", + "expect": { + "vendor": "Motorola", + "model": "XT2243-2", + "type": "mobile" + } + }, + { + "desc": "Motorola Moto X30 Pro", + "ua": "Mozilla/5.0 (Linux; U; Android 13; zh-CN; XT2241-1 Build/T1SQ33.111-12-19) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.58 UCBrowser/16.1.3.1264 Mobile Safari/537.36", + "expect": { + "vendor": "Motorola", + "model": "XT2241-1", + "type": "mobile" + } + }, + { + "desc": "Motorola Moto Z3 Play", + "ua": "Mozilla/5.0 (Linux; Android 9; Moto Z3 Play) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Motorola", + "model": "Moto Z3 Play", + "type": "mobile" + } + }, + { + "desc": "Motorola Moto Z4", + "ua": "Mozilla/5.0 (Linux; U; Android 10; moto z4 Build/QDF30.130-42-5-17; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/108.0.5359.128 Mobile Safari/537.36 OPR/2.3.0", + "expect": { + "vendor": "Motorola", + "model": "moto z4", + "type": "mobile" + } + }, + { + "desc": "Motorola Nexus 6", + "ua": "Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.20 Mobile Safari/537.36", + "expect": { + "vendor": "Motorola", + "model": "Nexus 6", + "type": "mobile" + } + }, + { + "desc": "Motorola One 5G", + "ua": "Mozilla/5.0 (Linux; Android 11; motorola one 5G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Mobile Safari/537.36", + "expect": { + "vendor": "Motorola", + "model": "one 5G", + "type": "mobile" + } + }, + { + "desc": "Motorola P30", + "ua": "Mozilla/5.0 (Linux; Android 8.1.0; XT1943-1 Build/OPM1.171019.019; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/97.0.4692.98 Mobile Safari/537.36 T7/13.50 SP-engine/2.88.0 baiduboxapp/13.50.5.10 (Baidu; P1 8.1.0) NABar/1.0", + "expect": { + "vendor": "Motorola", + "model": "XT1943-1", + "type": "mobile" + } + }, + { + "desc": "Motorola Razr 5G", + "ua": "Mozilla/5.0 (Linux; Android 12; motorola razr 5G Build/S2PS32.57-23-21; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/132.0.6834.97 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/497.0.0.47.36;IABMV/1;]", + "expect": { + "vendor": "Motorola", + "model": "razr 5G", + "type": "mobile" + } + }, + { + "desc": "Motorola Razr 5G", + "ua": "Mozilla/5.0 (Linux; Android 11; XT2071-4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "expect": { + "vendor": "Motorola", + "model": "XT2071-4", + "type": "mobile" + } + }, + { + "desc": "Motorola Razr 50 Ultra", + "ua": "Mozilla/5.0 (Linux; Android 14; motorola razr 50 ultra Build/U3UX34.56-29-2; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.260 Mobile Safari/537.36", + "expect": { + "vendor": "Motorola", + "model": "razr 50 ultra", + "type": "mobile" } } ] \ No newline at end of file diff --git a/test/data/ua/device/nothing.json b/test/data/ua/device/nothing.json index 56dc460..12b418d 100644 --- a/test/data/ua/device/nothing.json +++ b/test/data/ua/device/nothing.json @@ -17,6 +17,15 @@ "type": "mobile" } }, + { + "desc": "Nothing 2", + "ua": "Mozilla/5.0 (Linux; Android 15; AIN065 Build/AQ3A.240929.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/132.0.6834.90 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/496.0.0.45.65;IABMV/1;] FBNV/500", + "expect": { + "vendor": "Nothing", + "model": "AIN065", + "type": "mobile" + } + }, { "desc": "Nothing 2a", "ua": "Mozilla/5.0 (Linux; Android 14; A142 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/126.0.6478.71 Mobile Safari/537.36", @@ -25,5 +34,32 @@ "model": "A142", "type": "mobile" } + }, + { + "desc": "Nothing 2a Plus", + "ua": "Mozilla/5.0 (Linux; Android 14; A142P Build/UP1A.231005.007) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.107 Mobile Safari/537.36 OPX/2.6", + "expect": { + "vendor": "Nothing", + "model": "A142P", + "type": "mobile" + } + }, + { + "desc": "Nothing 3a", + "ua": "Mozilla/5.0 (Linux; Android 15; A059 Build/AQ3A.241015.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/127.0.6533.103 Mobile Safari/537.36", + "expect": { + "vendor": "Nothing", + "model": "A059", + "type": "mobile" + } + }, + { + "desc": "Nothing 3a Pro", + "ua": "Mozilla/5.0 (Linux; Android 15; A059P Build/AQ3A.241015.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/136.0.7103.57 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/511.0.0.73.36;IABMV/1;]", + "expect": { + "vendor": "Nothing", + "model": "A059P", + "type": "mobile" + } } ] \ No newline at end of file diff --git a/test/data/ua/device/oneplus.json b/test/data/ua/device/oneplus.json index 74ddcf6..a02c0f3 100644 --- a/test/data/ua/device/oneplus.json +++ b/test/data/ua/device/oneplus.json @@ -54,11 +54,20 @@ } }, { - "desc": "OnePlus 8T", - "ua": "Mozilla/5.0 (Linux; Android 11; KB2005) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.127 Mobile Safari/537.36", + "desc": "OnePlus 7T Pro", + "ua": "Mozilla/5.0 (Linux; Android 10; HD1913) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.5563.57 Mobile Safari/537.36 EdgA/110.0.1587.66", "expect": { "vendor": "OnePlus", - "model": "KB2005", + "model": "HD1913", + "type": "mobile" + } + }, + { + "desc": "OnePlus 8 Lite", + "ua": "Mozilla/5.0 (Linux; Android 10; OnePlus 8 Lite) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4741.47 Mobile Safari/537.36", + "expect": { + "vendor": "OnePlus", + "model": "8 Lite", "type": "mobile" } }, @@ -72,11 +81,191 @@ } }, { - "desc": "OnePlus Nord N100", - "ua": "Mozilla/5.0 (Linux; Android 10; BE2015 Build/QKQ1.200719.002; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Mobile Safari/537.36", + "desc": "OnePlus 8T", + "ua": "Mozilla/5.0 (Linux; Android 11; KB2005) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.127 Mobile Safari/537.36", "expect": { "vendor": "OnePlus", - "model": "BE2015", + "model": "KB2005", + "type": "mobile" + } + }, + { + "desc": "OnePlus 9", + "ua": "Mozilla/5.0 (Android 14; SDK 28; OnePlus 9) Gecko/128.0 Firefox/128.0", + "expect": { + "vendor": "OnePlus", + "model": "9", + "type": "mobile" + } + }, + { + "desc": "OnePlus 9", + "ua": "Mozilla/5.0 (Linux; Android 13; LE2113 Build/TP1A.220905.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/113.0.5672.162 Mobile Safari/537.36 Flipboard/4.3.14/5377,4.3.14.5377", + "expect": { + "vendor": "OnePlus", + "model": "LE2113", + "type": "mobile" + } + }, + { + "desc": "OnePlus 9 Pro", + "ua": "Mozilla/5.0 (Linux; Android 13; LE2123) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.128 Mobile Safari/537.36 OPR/73.0.3832.69371", + "expect": { + "vendor": "OnePlus", + "model": "LE2123", + "type": "mobile" + } + }, + { + "desc": "OnePlus 9R", + "ua": "Mozilla/5.0 (Linux; arm_64; Android 11; LE2100) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.85 YaApp_Android/21.114.1 YaSearchBrowser/21.114.1 BroPP/1.0 SA/3 Mobile Safari/537.36", + "expect": { + "vendor": "OnePlus", + "model": "LE2100", + "type": "mobile" + } + }, + { + "desc": "OnePlus 9RT 5G", + "ua": "Mozilla/5.0 (Linux; U; Android 11; en-in; MT2111 Build/RKQ1.210614.002) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30 GSA/13.14.15.23.arm64", + "expect": { + "vendor": "OnePlus", + "model": "MT2111", + "type": "mobile" + } + }, + { + "desc": "OnePlus 10 Pro", + "ua": "Mozilla/5.0 (Linux; arm_64; Android 12; NE2213) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.148 YaBrowser/22.7.5.90.00 SA/3 Mobile Safari/537.36", + "expect": { + "vendor": "OnePlus", + "model": "NE2213", + "type": "mobile" + } + }, + { + "desc": "OnePlus 10RT", + "ua": "Mozilla/5.0 (Linux; Android 13; CPH2413) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "OnePlus", + "model": "CPH2413", + "type": "mobile" + } + }, + { + "desc": "OnePlus 11R", + "ua": "Mozilla/5.0 (Linux; Android 14; CPH2487) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "OnePlus", + "model": "CPH2487", + "type": "mobile" + } + }, + { + "desc": "OnePlus 13", + "ua": "Mozilla/5.0 (Linux; Android 15; CPH2653 Build/AP3A.240617.008; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/134.0.6998.92 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/504.0.0.69.64;IABMV/1;] FBNV/5", + "expect": { + "vendor": "OnePlus", + "model": "CPH2653", + "type": "mobile" + } + }, + { + "desc": "OnePlus Ace", + "ua": "Mozilla/5.0 (Linux; U; Android 15; zh-cn; PGKM10 Build/AP3A.240617.008) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/115.0.5790.168 Mobile Safari/537.36 HeyTapBrowser/40.9.6.2", + "expect": { + "vendor": "OnePlus", + "model": "PGKM10", + "type": "mobile" + } + }, + { + "desc": "OnePlus Ace 2", + "ua": "Mozilla/5.0 (Linux; U; Android 14; zh-CN; PHK110 Build/UKQ1.231108.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.58 UCBrowser/17.3.6.1367 Mobile Safari/537.36", + "expect": { + "vendor": "OnePlus", + "model": "PHK110", + "type": "mobile" + } + }, + { + "desc": "OnePlus Ace 2 Pro", + "ua": "Mozilla/5.0 (Linux; arm; Android 13; PJA110) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 YaBrowser/23.1.0.284.00 (beta) SA/3 Mobile Safari/537.36", + "expect": { + "vendor": "OnePlus", + "model": "PJA110", + "type": "mobile" + } + }, + { + "desc": "OnePlus Ace 2V", + "ua": "Mozilla/5.0 (Linux; U; Android 15; zh-cn; PHP110 Build/AP3A.240617.008) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/121.0.6167.71 MQQBrowser/16.3 Mobile Safari/537.36 COVC/047707", + "expect": { + "vendor": "OnePlus", + "model": "PHP110", + "type": "mobile" + } + }, + { + "desc": "OnePlus Ace 3", + "ua": "Mozilla/5.0 (Linux; U; Android 15; zh-CN; PJE110 Build/TP1A.220905.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/123.0.6312.80 Quark/7.9.7.782 Mobile Safari/537.36", + "expect": { + "vendor": "OnePlus", + "model": "PJE110", + "type": "mobile" + } + }, + { + "desc": "OnePlus Ace 3 Pro 5G", + "ua": "Mozilla/5.0 (Linux; U; Android 15; zh-CN; PJX110 Build/UKQ1.231108.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/123.0.6312.80 Quark/7.11.4.814 Mobile Safari/537.36", + "expect": { + "vendor": "OnePlus", + "model": "PJX110", + "type": "mobile" + } + }, + { + "desc": "OnePlus Ace 3V", + "ua": "Mozilla/5.0 (Linux; U; Android 14; zh-cn; PJF110 Build/UP1A.231005.007) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/90.0.4430.61 Mobile Safari/537.36 HeyTapBrowser/40.8.33.1.2beta", + "expect": { + "vendor": "OnePlus", + "model": "PJF110", + "type": "mobile" + } + }, + { + "desc": "OnePlus Ace 5", + "ua": "Mozilla/5.0 (Linux; U; Android 15; zh-cn; PKG110 Build/UKQ1.231108.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/115.0.5790.168 Mobile Safari/537.36 HeyTapBrowser/40.9.9.2", + "expect": { + "vendor": "OnePlus", + "model": "PKG110", + "type": "mobile" + } + }, + { + "desc": "OnePlus Ace Pro", + "ua": "Mozilla/5.0 (Linux; U; Android 14; zh-CN; PGP110 Build/UKQ1.230924.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.58 UCBrowser/17.2.9.1360 Mobile Safari/537.36", + "expect": { + "vendor": "OnePlus", + "model": "PGP110", + "type": "mobile" + } + }, + { + "desc": "OnePlus Ace Racing Edition", + "ua": "Mozilla/5.0 (Linux; U; Android 13; zh-CN; PGZ110 Build/TP1A.220905.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.58 UCBrowser/17.3.6.1367 Mobile Safari/537.36", + "expect": { + "vendor": "OnePlus", + "model": "PGZ110", + "type": "mobile" + } + }, + { + "desc": "OnePlus Nord CE 4", + "ua": "Mozilla/5.0 (Linux; Android 14; CPH2613) AppleWebKit/537.36 (KHTML, like Gecko) JioSphere/5.0.4 Chrome/119.0.6045.193 Mobile Safari/537.36", + "expect": { + "vendor": "OnePlus", + "model": "CPH2613", "type": "mobile" } }, @@ -89,6 +278,33 @@ "type": "mobile" } }, + { + "desc": "OnePlus Nord N30 SE 5G", + "ua": "Mozilla/5.0 (Linux; Android 14; CPH2605 Build/TP1A.220905.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/135.0.7049.92 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/509.0.0.67.28;IABMV/1;]", + "expect": { + "vendor": "OnePlus", + "model": "CPH2605", + "type": "mobile" + } + }, + { + "desc": "OnePlus Nord N100", + "ua": "Mozilla/5.0 (Linux; Android 10; BE2015 Build/QKQ1.200719.002; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Mobile Safari/537.36", + "expect": { + "vendor": "OnePlus", + "model": "BE2015", + "type": "mobile" + } + }, + { + "desc": "OnePlus Open", + "ua": "Dalvik/2.1.0 (Linux; U; Android 15; CPH2551 Build/AP3A.240617.008)", + "expect": { + "vendor": "OnePlus", + "model": "CPH2551", + "type": "mobile" + } + }, { "desc": "OnePlus Pad Go 11.35", "ua": "Mozilla/5.0 (Linux; arm_64; Android 14; OPD2304) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.629 YaApp_Android/24.101/apad YaSearchBrowser/24.101/apad BroPP/1.0 SA/3 Mobile Safari/537.36", diff --git a/test/data/ua/device/oppo.json b/test/data/ua/device/oppo.json index 367039e..ab63e26 100644 --- a/test/data/ua/device/oppo.json +++ b/test/data/ua/device/oppo.json @@ -1,13 +1,4 @@ [ - { - "desc": "OnePlus 10RT", - "ua": "Mozilla/5.0 (Linux; Android 13; CPH2413) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36", - "expect": { - "vendor": "OPPO", - "model": "CPH2413", - "type": "mobile" - } - }, { "desc": "OPPO Pad", "ua": "Mozilla/5.0 (Linux; U; Android 13; zh-CN; OPD2101 Build/TP1A.220905.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.58 UCBrowser/16.3.9.1290 Mobile Safari/537.36", diff --git a/test/data/ua/device/retroid.json b/test/data/ua/device/retroid.json new file mode 100644 index 0000000..fc7a83d --- /dev/null +++ b/test/data/ua/device/retroid.json @@ -0,0 +1,11 @@ +[ + { + "desc": "Retroid Pocket 4 Pro", + "ua": "Mozilla/5.0 (Linux; arm_64; Android 13; Retroid Pocket 4 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.96 YaBrowser/24.4.3.96.00 SA/3 Mobile Safari/537.36", + "expect": { + "vendor": "Retroid", + "model": "Pocket 4 Pro", + "type": "console" + } + } +] \ No newline at end of file diff --git a/test/data/ua/device/samsung.json b/test/data/ua/device/samsung.json index 56e7b73..36b68db 100644 --- a/test/data/ua/device/samsung.json +++ b/test/data/ua/device/samsung.json @@ -296,6 +296,15 @@ "type": "smarttv" } }, + { + "desc": "Samsung SmartTV", + "ua": "Mozilla/5.0 (SMART-TV; Linux; Tizen 8.0) AppleWebKit/537.36 (KHTML, like Gecko) Samsung Browser/7.0 Chrome/108.0.5359.1 TV Safari/537.36", + "expect": { + "vendor": "Samsung", + "model": "undefined", + "type": "smarttv" + } + }, { "desc": "Samsung SmartTV HBBTV", "ua": "HbbTV/1.5.1 (+DRM;Samsung;SmartTV2021:UAU7000;T-KSU2EDEUC-1506.0;KantSU2e;urn:samsungtv:familyname:21_KANTSU2E_UHD_BASIC:2021;) Tizen/6.0 (+TVPLUS+SmartHubLink) Chrome/76 LaTivu_1.0.1_2021 RVID/17", diff --git a/test/data/ua/device/sony.json b/test/data/ua/device/sony.json index 92151af..d4a3c21 100644 --- a/test/data/ua/device/sony.json +++ b/test/data/ua/device/sony.json @@ -98,6 +98,15 @@ "type": "mobile" } }, + { + "desc": "Sony Xperia 1 VI", + "ua": "Mozilla/5.0 (Linux; Android 14; XQ-EC44) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Sony", + "model": "XQ-EC44", + "type": "mobile" + } + }, { "desc": "Sony Xperia 10ii", "ua": "Mozilla/5.0 (Linux; Android 10; XQ-AU52) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36", @@ -107,6 +116,24 @@ "type": "mobile" } }, + { + "desc": "Sony Xperia 10 III Lite", + "ua": "Mozilla/5.0 (Linux; Android 12; XQ-BT44 Build/62.1.A.1.227; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/101.0.4951.61 Mobile Safari/537.36 Sleipnir/3.6.0", + "expect": { + "vendor": "Sony", + "model": "XQ-BT44", + "type": "mobile" + } + }, + { + "desc": "Sony Xperia 10 VI", + "ua": "Mozilla/5.0 (Linux; Android 14; XQ-ES72 Build/70.0.A.2.233; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/129.0.6668.71 Mobile Safari/537.36 Line/14.16.0/IAB", + "expect": { + "vendor": "Sony", + "model": "XQ-ES72", + "type": "mobile" + } + }, { "desc": "Sony Xperia Pro", "ua": "Mozilla/5.0 (Linux; Android 10; XQ-AQ52) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.185 Mobile Safari/537.36", @@ -116,6 +143,24 @@ "type": "mobile" } }, + { + "desc": "Sony Xperia Pro", + "ua": "Mozilla/5.0 (Linux; Android 12; Sony XQ-AQ52) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/23.0 Chrome/115.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "Sony", + "model": "XQ-AQ52", + "type": "mobile" + } + }, + { + "desc": "Sony Xperia Pro I", + "ua": "Mozilla/5.0 (Linux; arm_64; Android 11; XQ-BE72) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.148 YaBrowser/22.7.3.82.00 SA/3 Mobile Safari/537.36", + "expect": { + "vendor": "Sony", + "model": "XQ-BE72", + "type": "mobile" + } + }, { "desc": "Sony SGP521 (Xperia Z2 Tablet)", "ua": "Mozilla/5.0 (Linux; Android 4.4; SGP521 Build/17.1.A.0.432) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.99 Safari/537.36", diff --git a/test/data/ua/device/tecno.json b/test/data/ua/device/tecno.json index a002fcf..4413f95 100644 --- a/test/data/ua/device/tecno.json +++ b/test/data/ua/device/tecno.json @@ -1,4 +1,31 @@ [ + { + "desc": "Tecno DroiPad 8D", + "ua": "Mozilla/5.0 (Linux; U; Android 5.1; TECNO DP8D Build/LMY47D; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Safari/537.36 OPR/42.0.2254.139280", + "expect": { + "vendor": "TECNO", + "model": "DP8D", + "type": "tablet" + } + }, + { + "desc": "Tecno DroiPad 10A Pro", + "ua": "Mozilla/5.0 (Linux; Android 5.1; TECNO DP10A Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.74 Safari/537.36", + "expect": { + "vendor": "TECNO", + "model": "DP10A Pro", + "type": "tablet" + } + }, + { + "desc": "Tecno DroiPad 10D 4G", + "ua": "Mozilla/5.0 (Linux; Android 7.0; TECNO P904) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Mobile Safari/537.36 OPR/77.0.4054.90", + "expect": { + "vendor": "TECNO", + "model": "P904", + "type": "tablet" + } + }, { "desc": "Tecno KC8", "ua": "Mozilla/5.0 (Linux; Android 10; TECNO KC8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36", diff --git a/test/data/ua/device/vizio.json b/test/data/ua/device/vizio.json new file mode 100644 index 0000000..d36ae4d --- /dev/null +++ b/test/data/ua/device/vizio.json @@ -0,0 +1,20 @@ +[ + { + "desc": "VIZIO", + "ua": "Mozilla/5.0 (X11; Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36 CrKey/1.0.999999 VIZIO SmartCast(Conjure/SX7B-4.6.419.12 FW/7.0.23.2-4 Model/M557-G0)", + "expect": { + "vendor": "VIZIO", + "model": "M557-G0", + "type": "smarttv" + } + }, + { + "desc": "VIZIO", + "ua": "VIZIO V506-J09 ViziOS/1.4.512.847.1 WatchFree/24.06.13.2 FancyPlayer/1.1.30-qa ", + "expect": { + "vendor": "VIZIO", + "model": "V506-J09", + "type": "smarttv" + } + } +] \ No newline at end of file diff --git a/test/data/ua/extension/crawler.json b/test/data/ua/extension/crawler.json index 8ed2d00..918ee98 100644 --- a/test/data/ua/extension/crawler.json +++ b/test/data/ua/extension/crawler.json @@ -259,6 +259,16 @@ "type" : "crawler" } }, + { + "desc" : "ChatGLM-Spider", + "ua" : "Mozilla/5.0 (compatible; ChatGLM-Spider/1.0; +https://chatglm.cn/)", + "expect" : + { + "name" : "ChatGLM-Spider", + "version" : "1.0", + "type" : "crawler" + } + }, { "desc" : "Coc Coc Bot (web)", "ua" : "Mozilla/5.0 (compatible; coccocbot-web/1.0; +http://help.coccoc.com/searchengine)", @@ -299,6 +309,36 @@ "type" : "crawler" } }, + { + "desc" : "Daum", + "ua" : "Mozilla/5.0 (compatible; MSIE or Firefox mutant;) Daum 4.1", + "expect" : + { + "name" : "Daum", + "version" : "4.1", + "type" : "crawler" + } + }, + { + "desc" : "Daumoa", + "ua" : "Mozilla/5.0 (compatible; MSIE or Firefox mutant; not on Windows server;) Daumoa 4.0", + "expect" : + { + "name" : "Daumoa", + "version" : "4.0", + "type" : "crawler" + } + }, + { + "desc" : "Daumoa-image", + "ua" : "Mozilla/5.0 (compatible; MSIE or Firefox mutant; not on Windows server;) Daumoa-image/1.0", + "expect" : + { + "name" : "Daumoa-image", + "version" : "1.0", + "type" : "crawler" + } + }, { "desc" : "Diffbot", "ua" : "Diffbot/0.1", @@ -489,6 +529,16 @@ "type" : "crawler" } }, + { + "desc" : "iAskBot", + "ua" : "Mozilla/5.0 AppleWebKit/605.1.15 (KHTML, like Gecko; compatible; iAskBot/1.0; +https://iask.ai/) Chrome/120.0.6099.119 Safari/605.1.15", + "expect" : + { + "name" : "iAskBot", + "version" : "1.0", + "type" : "crawler" + } + }, { "desc" : "ImagesiftBot", "ua" : "Mozilla/5.0 (compatible; ImagesiftBot; +imagesift.com)", @@ -580,6 +630,16 @@ "type" : "crawler" } }, + { + "desc" : "Onespot", + "ua" : "Mozilla/5.0 (compatible; Onespot-ScraperBot/1.0; +https://www.onespot.com/identifying-traffic.html)", + "expect" : + { + "name" : "Onespot-ScraperBot", + "version" : "1.0", + "type" : "crawler" + } + }, { "desc" : "OpenAI Search", "ua" : "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; OAI-SearchBot/1.0; +https://openai.com/searchbot", @@ -620,6 +680,36 @@ "type" : "crawler" } }, + { + "desc" : "Qwantbot", + "ua" : "Mozilla/5.0 (compatible; Qwantbot/1.0_12345; +https://help.qwant.com/bot/)", + "expect" : + { + "name" : "Qwantbot", + "version" : "1.0_12345", + "type" : "crawler" + } + }, + { + "desc" : "Qwantbot", + "ua" : "Mozilla/5.0 (compatible; Qwantbot-prod51071/1.0; +Qwantbot@qwant.com)", + "expect" : + { + "name" : "Qwantbot", + "version" : "1.0", + "type" : "crawler" + } + }, + { + "desc" : "Qwantbot", + "ua" : "Mozilla/5.0 (compatible; Qwantbot-news/2.0; +https://help.qwant.com/bot/)", + "expect" : + { + "name" : "Qwantbot", + "version" : "2.0", + "type" : "crawler" + } + }, { "desc" : "SemrushBot", "ua" : "Mozilla/5.0 (compatible; SemrushBot/7~bl; +http://www.semrush.com/bot.html)", @@ -680,6 +770,16 @@ "type" : "crawler" } }, + { + "desc" : "Startpage", + "ua" : "StartpagePrivateImageProxy/3.0 (https://www.startpage.com/; support@startpage.com) aiohttp.client/3.11.11", + "expect" : + { + "name" : "StartpagePrivateImageProxy", + "version" : "3.0", + "type" : "crawler" + } + }, { "desc" : "Teoma", "ua" : "Mozilla/2.0 (compatible; Ask Jeeves/Teoma; +http://sp.ask.com/docs/about/tech_crawling.html)", diff --git a/test/data/ua/extension/email.json b/test/data/ua/extension/email.json index 27fbce5..8acd5d4 100644 --- a/test/data/ua/extension/email.json +++ b/test/data/ua/extension/email.json @@ -9,6 +9,16 @@ "type" : "email" } }, + { + "desc" : "Apple Mail", + "ua" : "Mail/3826.500.181.1.5 CFNetwork/3826.500.111.1.1 Darwin/24.4.0", + "expect" : + { + "name" : "Mail", + "version" : "3826.500.181.1.5", + "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", @@ -29,6 +39,16 @@ "type" : "email" } }, + { + "desc" : "DaumMail", + "ua" : "DaumMobileApp (LG-KU5400; U; Android 2.3.7|10; ko-kr) DaumMail/1.0.8 ", + "expect" : + { + "name" : "DaumMail", + "version" : "1.0.8", + "type" : "email" + } + }, { "desc" : "Evolution", "ua" : "Evolution/3.52.3", @@ -119,6 +139,36 @@ "type" : "email" } }, + { + "desc" : "Polymail", + "ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Polymail/2.3.12 Chrome/114.0.5735.134 Electron/25.2.0 Safari/537.36", + "expect" : + { + "name" : "Polymail", + "version" : "2.3.12", + "type" : "email" + } + }, + { + "desc" : "ProtonMail", + "ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) ProtonMail/1.4.0 Chrome/122.0.6261.156 Electron/29.4.6 Safari/537.36", + "expect" : + { + "name" : "ProtonMail", + "version" : "1.4.0", + "type" : "email" + } + }, + { + "desc" : "SparkDesktop", + "ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) SparkDesktop/3.0.30 Chrome/102.0.5005.63 Electron/19.0.4 Safari/537.36", + "expect" : + { + "name" : "SparkDesktop", + "version" : "3.0.30", + "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", @@ -158,5 +208,25 @@ "version" : "1.3.10", "type" : "email" } + }, + { + "desc" : "Zimbra", + "ua" : "Mozilla/5.0 (Windows; U; Windows NT 6.2; it; rv:1.9.2.19pre) Gecko/20110902 Prism zdesktop/7.2.8", + "expect" : + { + "name" : "Zimbra", + "version" : "7.2.8", + "type" : "email" + } + }, + { + "desc" : "ZohoMail", + "ua" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) ZohoMail-Desktop/1.6.3 Chrome/124.0.6367.207 Electron/30.0.6 Safari/537.36", + "expect" : + { + "name" : "ZohoMail-Desktop", + "version" : "1.6.3", + "type" : "email" + } } ] diff --git a/test/data/ua/extension/fetcher.json b/test/data/ua/extension/fetcher.json index fed25bc..4a05393 100644 --- a/test/data/ua/extension/fetcher.json +++ b/test/data/ua/extension/fetcher.json @@ -129,6 +129,16 @@ "type" : "fetcher" } }, + { + "desc" : "Iframely", + "ua" : "Iframely/1.3.1 (+https://iframely.com/docs/about)", + "expect" : + { + "name" : "Iframely", + "version" : "1.3.1", + "type" : "fetcher" + } + }, { "desc" : "Meta-ExternalFetcher", "ua" : "meta-externalfetcher/1.1 (+https://developers.facebook.com/docs/sharing/webmasters/crawler)", @@ -149,6 +159,26 @@ "type" : "fetcher" } }, + { + "desc" : "MistralAI-User", + "ua" : "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; MistralAI-User/1.0; +https://docs.mistral.ai/robots)", + "expect" : + { + "name" : "MistralAI-User", + "version" : "1.0", + "type" : "fetcher" + } + }, + { + "desc" : "Perplexity-User", + "ua" : "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; Perplexity-User/1.0; +https://perplexity.ai/perplexity-user)", + "expect" : + { + "name" : "Perplexity-User", + "version" : "1.0", + "type" : "fetcher" + } + }, { "desc" : "Pinterestbot", "ua" : "Mozilla/5.0 (compatible; Pinterestbot/1.0; +http://www.pinterest.com/bot.html)", diff --git a/test/data/ua/extension/inapp.json b/test/data/ua/extension/inapp.json index 5512465..f1861c4 100644 --- a/test/data/ua/extension/inapp.json +++ b/test/data/ua/extension/inapp.json @@ -1,4 +1,154 @@ [ + { + "desc" : "Discord on Linux", + "ua" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) discord/0.0.26 Chrome/108.0.5359.215 Electron/22.3.2 Safari/537.36", + "expect" : + { + "name" : "discord", + "version" : "0.0.26", + "type" : "inapp" + } + }, + { + "desc" : "Discord on iPad", + "ua" : "Discord/52.0 (iPad; iOS 14.4; Scale/2.00)", + "expect" : + { + "name" : "Discord", + "version" : "52.0", + "type" : "inapp" + } + }, + { + "desc" : "Evernote on Windows", + "ua" : "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Evernote Windows/306387 (pt-PT, DDL); Windows/6.1.0 (Win32); Safari/537.36", + "expect" : + { + "name" : "Evernote", + "version" : "undefined", + "type" : "inapp" + } + }, + { + "desc" : "Figma on Mac", + "ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_4_0) AppleWebKit/537.36 (KHTML, like Gecko) Figma/99.0.0 Chrome/89.0.4389.128 Electron/12.0.9 Safari/537.36", + "expect" : + { + "name" : "Figma", + "version" : "99.0.0", + "type" : "inapp" + } + }, + { + "desc" : "Flipboard on Android", + "ua" : "Mozilla/5.0 (Linux; Android 8.0.0; SM-A720F Build/R16NW; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.110 Mobile Safari/537.36 Flipboard/4.1.13/4342,4.1.13.4342", + "expect" : + { + "name" : "Flipboard", + "version" : "4.1.13", + "type" : "inapp" + } + }, + { + "desc" : "Mattermost on Mac", + "ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_16_0) AppleWebKit/537.36 (KHTML, like Gecko) Mattermost/4.4.0 Chrome/76.0.3809.146 Electron/6.1.7 Safari/537.36", + "expect" : + { + "name" : "Mattermost", + "version" : "4.4.0", + "type" : "inapp" + } + }, + { + "desc" : "Mattermost on iPad", + "ua" : "Mattermost/1.49.1 (iPad; iOS 15.3.1; Scale/2.00)", + "expect" : + { + "name" : "Mattermost", + "version" : "1.49.1", + "type" : "inapp" + } + }, + { + "desc" : "Microsoft Teams on Mac", + "ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_3_1) AppleWebKit/537.36 (KHTML, like Gecko) Teams/1.8.00.3758 Chrome/126.0.6478.261 Electron/31.7.7 Safari/537.36", + "expect" : + { + "name" : "Teams", + "version" : "1.8.00.3758", + "type" : "inapp" + } + }, + { + "desc" : "Microsoft Teams on iPad", + "ua" : "Mozilla/5.0 (iPad; CPU OS 16_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 TeamsMobile-iOS", + "expect" : + { + "name" : "Teams", + "version" : "undefined", + "type" : "inapp" + } + }, + { + "desc" : "Microsoft Teams on iPhone", + "ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 TeamsMobile-iOS", + "expect" : + { + "name" : "Teams", + "version" : "undefined", + "type" : "inapp" + } + }, + { + "desc" : "Microsoft Teams on Android", + "ua" : "Mozilla/5.0 (Linux; Android 8.1.0; SM-G610F Build/M1AJQ; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/87.0.4280.101 Mobile Safari/537.36 TeamsMobile-Android", + "expect" : + { + "name" : "Teams", + "version" : "undefined", + "type" : "inapp" + } + }, + { + "desc" : "Notion on Mac", + "ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Notion/2.0.23 Chrome/91.0.4472.164 Electron/13.6.9 Safari/537.36", + "expect" : + { + "name" : "Notion", + "version" : "2.0.23", + "type" : "inapp" + } + }, + { + "desc" : "Postman on Mac", + "ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Postman/9.29.0 Chrome/94.0.4606.81 Electron/15.5.7 Safari/537.36", + "expect" : + { + "name" : "Postman", + "version" : "9.29.0", + "type" : "inapp" + } + }, + { + "desc" : "Rambox on mac", + "ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_16_0) AppleWebKit/537.36 (KHTML, like Gecko) Rambox/0.7.7 Chrome/78.0.3904.130 Electron/7.2.4 Safari/537.36", + "expect" : + { + "name" : "Rambox", + "version" : "0.7.7", + "type" : "inapp" + } + }, + { + "desc" : "Rocket.Chat on mac", + "ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Rocket.Chat/3.8.16 Chrome/106.0.5249.199 Electron/21.3.3 Safari/537.36", + "expect" : + { + "name" : "Rocket.Chat", + "version" : "3.8.16", + "type" : "inapp" + } + }, { "desc" : "Slack on mac", "ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Slack/4.39.90 Chrome/127.0.6533.72 Electron/13.1.9 Safari/537.36", @@ -9,6 +159,26 @@ "type" : "inapp" } }, + { + "desc" : "TikTok Lite", + "ua" : "Mozilla/5.0 (Linux; Android 8.0.0; SM-J400F Build/R16NW; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/68.0.3440.91 Mobile Safari/537.36 Channel/release AppName/ultralite app_version/27.2.3 Region/ID ByteLocale/id-ID ByteFullLocale/id-ID", + "expect" : + { + "name" : "TikTok Lite", + "version" : "27.2.3", + "type" : "inapp" + } + }, + { + "desc" : "VS Code on Windows", + "ua" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Code/1.85.1 Chrome/114.0.5735.289 Electron/25.9.7 Safari/537.36", + "expect" : + { + "name" : "VS Code", + "version" : "1.85.1", + "type" : "inapp" + } + }, { "desc" : "Yahoo! Japan on Android", "ua" : "Mozilla/5.0 (Linux; Android 13; SH-M20 Build/TKQ1.220915.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/132.0.6834.163 Mobile Safari/537.36 YJApp-ANDROID jp.co.yahoo.android.yjtop/3.187.0", diff --git a/test/data/ua/extension/library.json b/test/data/ua/extension/library.json index f691105..17435a2 100644 --- a/test/data/ua/extension/library.json +++ b/test/data/ua/extension/library.json @@ -1,4 +1,24 @@ [ + { + "desc" : "AdobeAIR", + "ua" : "Mozilla/5.0 (Windows; U; en-US) AppleWebKit/533.19.4 (KHTML, like Gecko) AdobeAIR/3.1", + "expect" : + { + "name" : "AdobeAIR", + "version" : "3.1", + "type" : "library" + } + }, + { + "desc" : "aiohttp", + "ua" : "Python/3.9 aiohttp/3.8.1", + "expect" : + { + "name" : "aiohttp", + "version" : "3.8.1", + "type" : "library" + } + }, { "desc" : "Apache-HttpClient", "ua" : "Apache-HttpClient/4.5.14 (Java/17.0.12)", @@ -109,6 +129,16 @@ "type" : "library" } }, + { + "desc" : "Nutch", + "ua" : "AliyunSecBot/Nutch-1.21-SNAPSHOT", + "expect" : + { + "name" : "Nutch", + "version" : "1.21-SNAPSHOT", + "type" : "library" + } + }, { "desc" : "OkHttp", "ua" : "okhttp/3.2.0", @@ -149,6 +179,16 @@ "type" : "library" } }, + { + "desc" : "Python httpx", + "ua" : "python-httpx/0.27.2", + "expect" : + { + "name" : "python-httpx", + "version" : "0.27.2", + "type" : "library" + } + }, { "desc" : "Python urllib", "ua" : "Python-urllib/2.6", @@ -159,6 +199,16 @@ "type" : "library" } }, + { + "desc" : "Python urllib3", + "ua" : "python-urllib3/1.26.18", + "expect" : + { + "name" : "python-urllib3", + "version" : "1.26.18", + "type" : "library" + } + }, { "desc" : "Python requests", "ua" : "python-requests/2.32", diff --git a/test/data/ua/os/aix.json b/test/data/ua/os/aix.json index 02ccda8..d45d1cb 100644 --- a/test/data/ua/os/aix.json +++ b/test/data/ua/os/aix.json @@ -7,5 +7,32 @@ "name" : "AIX", "version" : "undefined" } + }, + { + "desc" : "AIX", + "ua" : "Mozilla/5.0 (AIX; SPARC64; smart-thumbtack; Mosaic/2.7) Gecko/20100101 Mosaic/2.7", + "expect" : + { + "name" : "AIX", + "version" : "undefined" + } + }, + { + "desc" : "AIX", + "ua" : "Mozilla/5.0 (X11; N; Linux i686; en-US; rv:1.8.1.12) Gecko/20080219 Firefox/2.0.0.12 Mozilla/3.0 (X11; I; AIX 2) Navigator/9.0.0.6", + "expect" : + { + "name" : "AIX", + "version" : "2" + } + }, + { + "desc" : "AIX", + "ua" : "Mozilla/5.0 (X11; U; AIX 7.2; en-US; rv:1.7.12) Gecko/20100101 Firefox/126.0", + "expect" : + { + "name" : "AIX", + "version" : "7.2" + } } ] \ No newline at end of file diff --git a/test/data/ua/os/arcaos.json b/test/data/ua/os/arcaos.json new file mode 100644 index 0000000..5097545 --- /dev/null +++ b/test/data/ua/os/arcaos.json @@ -0,0 +1,20 @@ +[ + { + "desc" : "ArcaOS", + "ua" : "Mozilla/5.0 (OS/2; ArcaOS 5.0.6; x86_64; rv:89.0) Gecko/20100101 Firefox/89.0", + "expect" : + { + "name" : "ArcaOS", + "version" : "5.0.6" + } + }, + { + "desc" : "ArcaOS", + "ua" : "Mozilla/5.0 (OS/2; ArcaOS; x64; rv:89.0) Gecko/20100101 Firefox/89.0", + "expect" : + { + "name" : "ArcaOS", + "version" : "undefined" + } + } +] \ No newline at end of file diff --git a/test/data/ua/os/arch.json b/test/data/ua/os/arch.json index 0aad667..a186af0 100644 --- a/test/data/ua/os/arch.json +++ b/test/data/ua/os/arch.json @@ -1,4 +1,22 @@ [ + { + "desc" : "Arch", + "ua" : "Mozilla/5.0 (X11; Arch Linux i686; rv:2.0) Gecko/20100101 Firefox/126.1", + "expect" : + { + "name" : "Arch", + "version" : "undefined" + } + }, + { + "desc" : "Arch", + "ua" : "Mozilla/5.0 ArchLinux (X11; Linux x86_64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.41 Safari/535.1", + "expect" : + { + "name" : "Arch", + "version" : "undefined" + } + }, { "desc" : "Arch", "ua" : "Uzbl (Webkit 1.1.10) (Arch Linux)", diff --git a/test/data/ua/os/debian.json b/test/data/ua/os/debian.json index 4ae949a..a6a777b 100644 --- a/test/data/ua/os/debian.json +++ b/test/data/ua/os/debian.json @@ -52,5 +52,14 @@ "name" : "Debian", "version" : "undefined" } + }, + { + "desc" : "Debian", + "ua" : "Mozilla/5.0 (X11; U; Linux sparc64; es-PY; rv:5.0) Gecko/20100101 IceCat/5.0 (like Firefox/5.0; Debian-6.0.1)", + "expect" : + { + "name" : "Debian", + "version" : "6.0.1" + } } ] \ No newline at end of file diff --git a/test/data/ua/os/fuchsia.json b/test/data/ua/os/fuchsia.json index 0759cba..1f2e050 100644 --- a/test/data/ua/os/fuchsia.json +++ b/test/data/ua/os/fuchsia.json @@ -7,5 +7,14 @@ "name" : "Fuchsia", "version" : "undefined" } + }, + { + "desc" : "Fuchsia", + "ua" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Mozilla/5.0 (X11; Linux; Fuchsia; GoogleTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Large Screen Safari/537.36 GoogleTV", + "expect" : + { + "name" : "Fuchsia", + "version" : "undefined" + } } ] \ No newline at end of file diff --git a/test/data/ua/os/haiku.json b/test/data/ua/os/haiku.json index 7005087..f253739 100644 --- a/test/data/ua/os/haiku.json +++ b/test/data/ua/os/haiku.json @@ -7,5 +7,32 @@ "name" : "Haiku", "version" : "R1" } + }, + { + "desc" : "Haiku", + "ua" : "Mozilla/5.0 (X11; Haiku x86_64; rv:128.0) Gecko/20100101 Firefox/128.0", + "expect" : + { + "name" : "Haiku", + "version" : "undefined" + } + }, + { + "desc" : "Haiku", + "ua" : "Mozilla/5.0 (Haiku; BeOS; rv:99.0) Gecko/20100101 Firefox/99.0", + "expect" : + { + "name" : "Haiku", + "version" : "undefined" + } + }, + { + "desc" : "Haiku", + "ua" : "Mozilla/5.0 (X11; Haiku BePC) AppleWebKit/537.36 (KHTML, like Gecko) QtWebEngine/5.15.17 Chrome/87.0.4280.144 Safari/537.36 Dooble/2023.12.25 Dooble/2023.12.25", + "expect" : + { + "name" : "Haiku", + "version" : "undefined" + } } ] \ No newline at end of file diff --git a/test/data/ua/os/harmonyos.json b/test/data/ua/os/harmonyos.json index 1fa13ef..c201654 100644 --- a/test/data/ua/os/harmonyos.json +++ b/test/data/ua/os/harmonyos.json @@ -5,7 +5,52 @@ "expect" : { "name" : "HarmonyOS", - "version" : "10" + "version" : "undefined" + } + }, + { + "desc" : "HarmonyOS 2", + "ua" : "Mozilla/5.0 (Linux; Android 10; STK-AL00 Build/HUAWEISTK-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/88.0.4324.93 Mobile Safari/537.36 BDOS/1.0 (HarmonyOS 2.2.0) SP-engine/2.72.0 baiduboxapp/13.34.5.10 (Baidu; P1 10) NABar/1.0", + "expect" : + { + "name" : "HarmonyOS", + "version" : "2.2.0" + } + }, + { + "desc" : "HarmonyOS 3", + "ua" : "Mozilla/5.0 (Linux; Android 12; Huawei P60 Pro Build/HarmonyOS 3.1.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.1.6136.139 Mobile Safari/537.36 OPR/111.11", + "expect" : + { + "name" : "HarmonyOS", + "version" : "3.1.0" + } + }, + { + "desc" : "HarmonyOS 4", + "ua" : "Mozilla/5.0 (Android 12; HarmonyOS 4.0.0.118; OXF-AN00 Build/HUAWEIOXF-AN00; HMSCore 6.13.0.302; wv) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Mobile Safari/537.36 EdgA/125.0.0.0 Language/zh_TW ABI/arm64-v8a", + "expect" : + { + "name" : "HarmonyOS", + "version" : "4.0.0.118" + } + }, + { + "desc" : "HarmonyOS 4", + "ua" : "Mozilla/5.0 (Linux; Android 12; HarmonyOS/4.0.3.601; JAD-AL50; HMSCore/6.13.0.320 Build/AP31.240223.016.A3; x64; ARM64) AppleWebKit/537.36 (KHTML, like Gecko) HuaweiBrowser/14.0.7.302 Mobile Safari/537.36", + "expect" : + { + "name" : "HarmonyOS", + "version" : "4.0.3.601" + } + }, + { + "desc" : "HarmonyOS 5", + "ua" : "Mozilla/5.0 (PC; OpenHarmony 5.0; HarmonyOS 5.0) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/114.0.0.0 Safari/537.36 ArkWeb/4.1.6.1 Browser/harmony360Browser/1.0.0", + "expect" : + { + "name" : "HarmonyOS", + "version" : "5.0" } } ] \ No newline at end of file diff --git a/test/data/ua/os/knoppix.json b/test/data/ua/os/knoppix.json new file mode 100644 index 0000000..4ca6cdb --- /dev/null +++ b/test/data/ua/os/knoppix.json @@ -0,0 +1,11 @@ +[ + { + "desc" : "Knoppix", + "ua" : "Mozilla/5.0 (Knoppix; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.3", + "expect" : + { + "name" : "Knoppix", + "version" : "undefined" + } + } +] \ No newline at end of file diff --git a/test/data/ua/os/kubuntu.json b/test/data/ua/os/kubuntu.json index 2634256..d242142 100644 --- a/test/data/ua/os/kubuntu.json +++ b/test/data/ua/os/kubuntu.json @@ -7,5 +7,14 @@ "name" : "Kubuntu", "version" : "undefined" } + }, + { + "desc" : "Kubuntu", + "ua" : "Mozilla/5.0 (Kubuntu; Linux x86_64; rv:124.0) Gecko/20100101 Firefox/124.0", + "expect" : + { + "name" : "Kubuntu", + "version" : "undefined" + } } ] \ No newline at end of file diff --git a/test/data/ua/os/mint.json b/test/data/ua/os/mint.json index e87641e..8493d1a 100644 --- a/test/data/ua/os/mint.json +++ b/test/data/ua/os/mint.json @@ -25,5 +25,104 @@ "name" : "Mint", "version" : "6" } + }, + { + "desc" : "Mint", + "ua" : "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/2008121622 Linux Mint/6 (Felicia) Firefox/3.0.4", + "expect" : + { + "name" : "Mint", + "version" : "6" + } + }, + { + "desc" : "Mint", + "ua" : "Opera/9.80 (X11; Linux i686; Edition Linux Mint) Presto/2.12.388 Version/12.15", + "expect" : + { + "name" : "Mint", + "version" : "undefined" + } + }, + { + "desc" : "Mint", + "ua" : "Opera/9.51 (X11; Linux i686; U; Linux Mint; en)", + "expect" : + { + "name" : "Mint", + "version" : "undefined" + } + }, + { + "desc" : "Mint", + "ua" : "Mozilla/5.0 (X11; Linux Mint/19.3 x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Brave Chrome/83.0.4103.97 Safari/537.36", + "expect" : + { + "name" : "Mint", + "version" : "19.3" + } + }, + { + "desc" : "Mint", + "ua" : "Mozilla/5.0 (X11; Linux Mint/20 x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Kiwi Chrome/100.0.0.0 Safari/537.36", + "expect" : + { + "name" : "Mint", + "version" : "20" + } + }, + { + "desc" : "Mint", + "ua" : "Mozilla/5.0 (X11; Linux Mint/20.2; x86_64) Gecko/20100101 Firefox/92.0.1", + "expect" : + { + "name" : "Mint", + "version" : "20.2" + } + }, + { + "desc" : "Mint", + "ua" : "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.9.0.10) Gecko/2009042513 Linux Mint/5 (Elyssa) Firefox/3.0.10", + "expect" : + { + "name" : "Mint", + "version" : "5" + } + }, + { + "desc" : "Mint", + "ua" : "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.11) Gecko/2009060308 Linux Mint/7 (Gloria) Firefox/54.0", + "expect" : + { + "name" : "Mint", + "version" : "7" + } + }, + { + "desc" : "Mint", + "ua" : "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.3) Gecko/20091020 Linux Mint/8 (Helena) Firefox/3.5.3", + "expect" : + { + "name" : "Mint", + "version" : "8" + } + }, + { + "desc" : "Mint", + "ua" : "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:2.0) Gecko/20100101 Linux Mint 16/Petra Firefox/25.0.1.", + "expect" : + { + "name" : "Mint", + "version" : "16" + } + }, + { + "desc" : "Mint", + "ua" : "Mozilla/5.0 (Linux x86_64; Mint 21.3) AppleWebKit/537.36 (KHTML, like Gecko) Brave/128.0.0.0 Safari/537.36", + "expect" : + { + "name" : "Mint", + "version" : "21.3" + } } ] \ No newline at end of file diff --git a/test/data/ua/os/morphos.json b/test/data/ua/os/morphos.json index f255eeb..e540858 100644 --- a/test/data/ua/os/morphos.json +++ b/test/data/ua/os/morphos.json @@ -7,5 +7,32 @@ "name" : "MorphOS", "version" : "undefined" } + }, + { + "desc" : "MorphOS", + "ua" : "Mozilla/5.0 (Macintosh; PowerPC MorphOS 3.7; Odyssey Web Browser; rv:1.23) AppleWebKit/538.1 (KHTML, like Gecko) OWB/1.23 Safari/538.1", + "expect" : + { + "name" : "MorphOS", + "version" : "3.7" + } + }, + { + "desc" : "MorphOS", + "ua" : "Mozilla/5.0 (X11; MorphOS ppc64; rv:88.0) Gecko/20100101 Firefox/88.0", + "expect" : + { + "name" : "MorphOS", + "version" : "undefined" + } + }, + { + "desc" : "MorphOS", + "ua" : "Mozilla/5.0 (compatible; Origyn Web Browser; MorphOS; PPC; U) AppleWebKit/528.5+ (KHTML, like Gecko, Safari/528.5+)", + "expect" : + { + "name" : "MorphOS", + "version" : "undefined" + } } ] \ No newline at end of file diff --git a/test/data/ua/os/os2.json b/test/data/ua/os/os2.json index cb38c11..56eac7c 100644 --- a/test/data/ua/os/os2.json +++ b/test/data/ua/os/os2.json @@ -7,5 +7,23 @@ "name" : "OS/2", "version" : "undefined" } + }, + { + "desc" : "OS/2", + "ua" : "Mozilla/5.0 (OS/2; OS/2 i386) AppleWebKit/538.36 (KHTML, like Gecko) QtWebEngine/5.15.2 Chrome/127.0.6533.72", + "expect" : + { + "name" : "OS/2", + "version" : "undefined" + } + }, + { + "desc" : "OS/2", + "ua" : "Mozilla/5.0 (OS/2; Warp 4.5; rv:45.0) Gecko/20100101 Firefox/45.0", + "expect" : + { + "name" : "OS/2", + "version" : "undefined" + } } ] \ No newline at end of file diff --git a/test/data/ua/os/solaris.json b/test/data/ua/os/solaris.json index 450e47d..4c8f673 100644 --- a/test/data/ua/os/solaris.json +++ b/test/data/ua/os/solaris.json @@ -5,7 +5,16 @@ "expect" : { "name" : "Solaris", - "version" : "sun4u" + "version" : "undefined" + } + }, + { + "desc" : "Solaris", + "ua" : "Mozilla/5.0 (Solaris; SPARC; w3m/0.5.3; rv:1.0) Gecko/20100101 w3m/0.5.3", + "expect" : + { + "name" : "Solaris", + "version" : "undefined" } }, { @@ -16,5 +25,23 @@ "name" : "Solaris", "version" : "4.1.4" } + }, + { + "desc" : "Solaris", + "ua" : "Opera/5.0 (SunOS 5.8 sun4m; U) [en]", + "expect" : + { + "name" : "Solaris", + "version" : "5.8" + } + }, + { + "desc" : "Solaris", + "ua" : "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.8) Gecko/20100215 Solaris/10.1 (GNU) Superswan/3.5.8 (Byte/me)", + "expect" : + { + "name" : "Solaris", + "version" : "10.1" + } } ] \ No newline at end of file diff --git a/test/data/ua/os/suse.json b/test/data/ua/os/suse.json index 9da3f35..57f5f69 100644 --- a/test/data/ua/os/suse.json +++ b/test/data/ua/os/suse.json @@ -7,5 +7,14 @@ "name" : "SUSE", "version" : "3.6.17-0.2.1" } + }, + { + "desc" : "SUSE", + "ua" : "Mozilla/5.0 (X11; SUSE; Linux amd64; rv:86.0) Gecko/20100101 Firefox/86.0", + "expect" : + { + "name" : "SUSE", + "version" : "undefined" + } } ] \ No newline at end of file diff --git a/test/data/ua/os/ubuntu.json b/test/data/ua/os/ubuntu.json index d3958f9..5438e89 100644 --- a/test/data/ua/os/ubuntu.json +++ b/test/data/ua/os/ubuntu.json @@ -16,5 +16,32 @@ "name" : "Ubuntu", "version" : "undefined" } + }, + { + "desc" : "Ubuntu", + "ua" : "Mozilla/5.0 (Wayland; Linux x86_64; Huawei) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Ubuntu/23.04 Edg/110.0.1587.41", + "expect" : + { + "name" : "Ubuntu", + "version" : "23.04" + } + }, + { + "desc" : "Ubuntu", + "ua" : "Mozilla/5.0 (X11; Ubuntu 20.04; Linux arm; rv:99.0) Gecko/20100101 Firefox/99.0", + "expect" : + { + "name" : "Ubuntu", + "version" : "20.04" + } + }, + { + "desc" : "Ubuntu", + "ua" : "Opera/9.80 (X11; Linux i686; Ubuntu/14.10) Presto/2.12.388 Version/12.16", + "expect" : + { + "name" : "Ubuntu", + "version" : "14.10" + } } ] \ No newline at end of file diff --git a/test/data/ua/os/webos.json b/test/data/ua/os/webos.json index c31cd3f..7f3d04a 100644 --- a/test/data/ua/os/webos.json +++ b/test/data/ua/os/webos.json @@ -1,6 +1,6 @@ [ { - "desc" : "WebOS", + "desc" : "HP WebOS", "ua" : "Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.5; U; en-US) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/234.83 Safari/534.6 TouchPad/1.0", "expect" : { @@ -9,7 +9,7 @@ } }, { - "desc" : "WebOS", + "desc" : "Palm WebOS", "ua" : "Mozilla/5.0 (webOS/1.4.5; U; en-US) AppleWebKit/532.2 (KHTML, like Gecko) Version/1.0 Safari/532.2 Pre/1.0", "expect" : { @@ -17,13 +17,58 @@ "version" : "1.4.5" } }, + { + "desc" : "WebOS TV 22", + "ua" : " Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chr0me/87.0.4280.88 Safari/537.36 LG Browser/8.00.00(LGE; ST50K-LG2200WEB; 04.42.26; 0x00000001; DTV_C22P); webOS.TV-2022; LG NetCast.TV-2013 Compatible (LGE, ST50K-LG2200WEB, wireless)", + "expect" : + { + "name" : "webOS", + "version" : "22" + } + }, + { + "desc" : "WebOS TV 22", + "ua" : "Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 HbbTV/1.6.1 (+DRM; LGE/SILICONPLAYER/Hyundai; 50HYN3205; WEBOS22 04.42.26; W22_K8LP; DTV_C22P;)", + "expect" : + { + "name" : "webOS", + "version" : "22" + } + }, + { + "desc" : "WebOS TV 5.0", + "ua" : "Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chr0me/68.0.3440.106 Safari/537.36 LG Browser/8.00.00(LGE; SWU-6522; 04.50.63; 0x00000001; DTV_C20P); webOS.TV-2020; LG NetCast.TV-2013 Compatible (LGE, SWU-6522, wireless)", + "expect" : + { + "name" : "webOS", + "version" : "5" + } + }, + { + "desc" : "WebOS TV 5.0", + "ua" : "Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36 HbbTV/1.5.1 (+DRM; LGE/WALTON/Hyundai; 50HYN3205; WEBOS5.0 04.50.63; W50_K6LP; DTV_C20P;)", + "expect" : + { + "name" : "webOS", + "version" : "5.0" + } + }, { "desc" : "WebOS TV 5.x", "ua" : "Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36 WebAppManager", "expect" : { "name" : "webOS", - "version" : "TV" + "version" : "5" + } + }, + { + "desc" : "WebOS TV 5.x", + "ua" : "Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chr0me/68.0.3440.106 Safari/537.36 LG Browser/8.00.00(LGE; E65A71B-S; 04.50.63; 0x00000001; DTV_C20P); webOS.TV-2020; LG NetCast.TV-2013 Compatible (LGE, E65A71B-S, wired)", + "expect" : + { + "name" : "webOS", + "version" : "5" } }, { @@ -32,7 +77,16 @@ "expect" : { "name" : "webOS", - "version" : "TV" + "version" : "4" + } + }, + { + "desc" : "WebOS TV 3.5", + "ua" : "Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 HbbTV/1.3.1 ( DRM; LGE; OLED55B7V-T; WEBOS3.5 06.10.60; W3_M16P; ) FVC/2.0 (LGE; WEBOS3.5 ;)", + "expect" : + { + "name" : "webOS", + "version" : "3.5" } }, { @@ -41,7 +95,7 @@ "expect" : { "name" : "webOS", - "version" : "TV" + "version" : "3" } }, { @@ -50,7 +104,7 @@ "expect" : { "name" : "webOS", - "version" : "TV" + "version" : "2" } }, { @@ -59,7 +113,7 @@ "expect" : { "name" : "webOS", - "version" : "TV" + "version" : "1" } } ] \ No newline at end of file diff --git a/test/data/ua/os/windows-ce.json b/test/data/ua/os/windows-ce.json new file mode 100644 index 0000000..a28eb17 --- /dev/null +++ b/test/data/ua/os/windows-ce.json @@ -0,0 +1,20 @@ +[ + { + "desc" : "Windows CE", + "ua" : "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11)", + "expect" : + { + "name" : "Windows CE", + "version" : "undefined" + } + }, + { + "desc" : "Windows CE", + "ua" : "Mozilla/4.0 (PDA; Windows CE/1.0.1) NetFront/3.0", + "expect" : + { + "name" : "Windows CE", + "version" : "1.0.1" + } + } +] \ No newline at end of file diff --git a/test/data/ua/os/windows-mobile.json b/test/data/ua/os/windows-mobile.json index 5baf78c..78df88b 100644 --- a/test/data/ua/os/windows-mobile.json +++ b/test/data/ua/os/windows-mobile.json @@ -16,5 +16,23 @@ "name" : "Windows Mobile", "version" : "undefined" } + }, + { + "desc" : "Windows Mobile", + "ua" : "Opera/9.7 (Windows Mobile; PPC; Opera Mobi/35166; U; en) Presto/2.2.1", + "expect" : + { + "name" : "Windows Mobile", + "version" : "undefined" + } + }, + { + "desc" : "Windows Mobile 6.1", + "ua" : "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11) 320x240; VZW; Motorola-Q9c; Windows Mobile 6.1 Standard", + "expect" : + { + "name" : "Windows Mobile", + "version" : "6.1" + } } ] \ No newline at end of file diff --git a/test/data/ua/os/windows-phone.json b/test/data/ua/os/windows-phone.json index a6a8b82..bf4bd0a 100644 --- a/test/data/ua/os/windows-phone.json +++ b/test/data/ua/os/windows-phone.json @@ -9,14 +9,32 @@ } }, { - "desc" : "Windows Phone OS", + "desc" : "Windows Phone 6.5", + "ua" : "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; HTC_Touch2_T3333; Windows Phone 6.5)", + "expect" : + { + "name" : "Windows Phone", + "version" : "6.5" + } + }, + { + "desc" : "Windows Phone 7.0", "ua" : "Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0; DELL; Venue Pro)", "expect" : { - "name" : "Windows Phone OS", + "name" : "Windows Phone", "version" : "7.0" } }, + { + "desc" : "Windows Phone 7.5", + "ua" : "Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; NOKIA; Lumia 800)", + "expect" : + { + "name" : "Windows Phone", + "version" : "7.5" + } + }, { "desc" : "Windows Phone 8", "ua" : "Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; HTC; Windows Phone 8X by HTC)", @@ -25,5 +43,14 @@ "name" : "Windows Phone", "version" : "8.0" } + }, + { + "desc" : "Windows Phone 8.1", + "ua" : "Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 635) like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537", + "expect" : + { + "name" : "Windows Phone", + "version" : "8.1" + } } ] \ No newline at end of file diff --git a/test/data/ua/os/windows-rt.json b/test/data/ua/os/windows-rt.json new file mode 100644 index 0000000..8bee151 --- /dev/null +++ b/test/data/ua/os/windows-rt.json @@ -0,0 +1,20 @@ +[ + { + "desc" : "Windows RT 8", + "ua" : "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; ARM; Trident/6.0)", + "expect" : + { + "name" : "Windows RT", + "version" : "8" + } + }, + { + "desc" : "Windows RT 8.1", + "ua" : "Mozilla/5.0 (Windows NT 6.3; ARM; Trident/7.0; Touch; rv:11.0) like Gecko", + "expect" : + { + "name" : "Windows RT", + "version" : "8.1" + } + } +] \ No newline at end of file diff --git a/test/data/ua/os/windows.json b/test/data/ua/os/windows.json index 39e9541..faa9652 100644 --- a/test/data/ua/os/windows.json +++ b/test/data/ua/os/windows.json @@ -1,4 +1,103 @@ [ + { + "desc" : "Windows 3.1", + "ua" : "NCSA_Mosaic/2.0 (Windows 3.1)", + "expect" : + { + "name" : "Windows", + "version" : "3.1" + } + }, + { + "desc" : "Windows 3.1", + "ua" : "Mozilla/1.22 (compatible; MSIE 2.0; Windows 3.1)", + "expect" : + { + "name" : "Windows", + "version" : "3.1" + } + }, + { + "desc" : "Windows NT", + "ua" : "Mozilla/4.51 [de] (WinNT; I)", + "expect" : + { + "name" : "Windows", + "version" : "NT" + } + }, + { + "desc" : "Windows NT 3.51", + "ua" : "Mozilla/4.0 (compatible; MSIE 4.0; Windows NT)", + "expect" : + { + "name" : "Windows", + "version" : "NT" + } + }, + { + "desc" : "Windows NT 3.51", + "ua" : "Mozilla/4.0 (compatible; MSIE 5.05; Windows NT 3.51)", + "expect" : + { + "name" : "Windows", + "version" : "NT 3.51" + } + }, + { + "desc" : "Windows NT 4.0", + "ua" : "Opera/8.41.(Windows NT 4.0; ts-ZA) Presto/2.9.178 Version/11.00", + "expect" : + { + "name" : "Windows", + "version" : "NT 4.0" + } + }, + { + "desc" : "Windows NT 4.0", + "ua" : "Mozilla/5.0 (Windows; U; WinNT4.0; de-DE; rv:1.7.5) Gecko/20041108 Firefox/52.7.4", + "expect" : + { + "name" : "Windows", + "version" : "NT 4.0" + } + }, + { + "desc" : "Netscape on Windows 95", + "ua" : "Mozilla/5.0 (Windows; U; Win95; de-DE; rv:0.9.2) Gecko/20010726 Netscape6/6.1", + "expect" : + { + "name" : "Windows", + "version" : "95" + } + }, + { + "desc" : "Windows 95", + "ua" : "Mozilla/3.0 (Win95)", + "expect" : + { + "name" : "Windows", + "version" : "95" + } + }, + { + "desc" : "Windows 95", + "ua" : "Mozilla/3.0 (compatible; Opera/3.0; Windows 95/NT4) 3.2", + "expect" : + { + "name" : "Windows", + "version" : "95" + } + }, + { + "desc" : "Windows 95", + "ua" : "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95) Opera 6.02 [en]", + "expect" : + { + "name" : "Windows", + "version" : "95" + } + }, { "desc" : "Windows 95", "ua" : "Mozilla/1.22 (compatible; MSIE 2.0; Windows 95)", @@ -17,6 +116,24 @@ "version" : "98" } }, + { + "desc" : "Firebird on Windows 98", + "ua" : "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.5) Gecko/20031007 Firebird/0.7", + "expect" : + { + "name" : "Windows", + "version" : "98" + } + }, + { + "desc" : "K-Meleon on Windows 98", + "ua" : "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.5) Gecko/20031016 K-Meleon/0.8.2", + "expect" : + { + "name" : "Windows", + "version" : "98" + } + }, { "desc" : "Windows ME", "ua" : "Mozilla/5.0 (Windows; U; Win 9x 4.90) Gecko/20020502 CS 2000 7.0/7.0", @@ -26,6 +143,51 @@ "version" : "ME" } }, + { + "desc" : "Opera on Windows ME", + "ua" : "Mozilla/4.0 (compatible; MSIE 5.0; Windows ME) Opera 5.12 [de]", + "expect" : + { + "name" : "Windows", + "version" : "ME" + } + }, + { + "desc" : "Netscape on Windows ME", + "ua" : "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.8.1.8pre) Gecko/20071015 Firefox/2.0.0.7 Navigator/9.0", + "expect" : + { + "name" : "Windows", + "version" : "ME" + } + }, + { + "desc" : "Netscape on Windows 2000", + "ua" : "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20050519 Netscape/8.0.1", + "expect" : + { + "name" : "Windows", + "version" : "2000" + } + }, + { + "desc" : "Opera on Windows 2000", + "ua" : "Opera/6.05 (Windows 2000; U)", + "expect" : + { + "name" : "Windows", + "version" : "2000" + } + }, + { + "desc" : "Opera on Windows 2000", + "ua" : "Opera/9.69 (Windows NT 5.01; en-US) Presto/2.8.160 Version/10.00", + "expect" : + { + "name" : "Windows", + "version" : "2000" + } + }, { "desc" : "Windows 2000", "ua" : "Mozilla/3.0 (compatible; MSIE 3.0; Windows NT 5.0)", @@ -44,6 +206,15 @@ "version" : "XP" } }, + { + "desc" : "Windows XP", + "ua" : "Mozilla/5.0 (Windows XP; U) Opera 6.05 [de]", + "expect" : + { + "name" : "Windows", + "version" : "XP" + } + }, { "desc" : "Windows Vista", "ua" : "Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 6.0; fr-FR)", @@ -53,6 +224,33 @@ "version" : "Vista" } }, + { + "desc" : "Windows 7", + "ua" : "Microsoft Windows 7", + "expect" : + { + "name" : "Windows", + "version" : "7" + } + }, + { + "desc" : "Windows 7", + "ua" : "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Evernote Windows/306387 (pt-PT, DDL); Windows/6.1.0 (Win32); Safari/537.36", + "expect" : + { + "name" : "Windows", + "version" : "7" + } + }, + { + "desc" : "Windows 7", + "ua" : "Mozilla/5.0 (Windows 7 Enterprise; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6099.71 Safari/537.36", + "expect" : + { + "name" : "Windows", + "version" : "7" + } + }, { "desc" : "Windows 7", "ua" : "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)", @@ -71,6 +269,15 @@ "version" : "8" } }, + { + "desc" : "Windows 8.1", + "ua" : "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:66.0.5) Gecko/20100101 Firefox/66.0.5", + "expect" : + { + "name" : "Windows", + "version" : "8.1" + } + }, { "desc" : "Windows 10", "ua" : "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0", @@ -80,6 +287,15 @@ "version" : "10" } }, + { + "desc" : "Windows Server 2012 R2", + "ua" : "Mozilla/5.0 (Windows Server 2012 R2 Standard; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.5975.80 Safari/537.36", + "expect" : + { + "name" : "Windows", + "version" : "Server 2012 R2" + } + }, { "desc" : "WeChat Desktop for Windows Built-in Browser", "ua" : "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 MicroMessenger/6.5.2.501 NetType/WIFI WindowsWechat QBCore/3.43.901.400 QQBrowser/9.0.2524.400", @@ -99,48 +315,75 @@ } }, { - "desc" : "Windows RT", - "ua" : "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; ARM; Trident/6.0)", - "expect" : - { - "name" : "Windows", - "version" : "RT" - } - }, - { - "desc" : "Windows CE", - "ua" : "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11)", - "expect" : - { - "name" : "Windows", - "version" : "CE" - } - }, - { - "desc" : "Windows NT on x86 or aarch64 CPU using Firefox", - "ua" : "Mozilla/5.0 (Windows NT x.y; rv:10.0) Gecko/20100101 Firefox/10.0", - "expect" : - { - "name" : "Windows", - "version" : "NT x" - } - }, - { - "desc" : "Windows NT on x64 CPU using Firefox", - "ua" : "Mozilla/5.0 (Windows NT x.y; Win64; x64; rv:10.0) Gecko/20100101 Firefox/10.0", - "expect" : - { - "name" : "Windows", - "version" : "NT x" - } - }, - { - "desc" : "iTunes Windows Vista", + "desc" : "iTunes on Windows Vista", "ua" : "iTunes/10.7 (Windows; Microsoft Windows Vista Home Premium Edition Service Pack 1 (Build 6001)) AppleWebKit/536.26.9", "expect" : { "name" : "Windows", "version" : "Vista" } + }, + { + "desc" : "iTunes on Windows 7", + "ua" : "iTunes/10.6.3 (Windows; Microsoft Windows 7 x64 Business Edition Service Pack 1 (Build 7601)) AppleWebKit/534.57.2", + "expect" : + { + "name" : "Windows", + "version" : "7" + } + }, + { + "desc" : "iTunes on Windows 8", + "ua" : "iTunes/12.1.1 (Windows; Microsoft Windows 8 x64 Business Edition (Build 9200)) AppleWebKit/7600.1017.9000.2", + "expect" : + { + "name" : "Windows", + "version" : "8" + } + }, + { + "desc" : "iTunes on Windows 8.1", + "ua" : "iTunes/12.4 (Windows; Microsoft Windows 8.1 x64 Business Edition (Build 9200); x64) AppleWebKit/7601.6016.1000.1", + "expect" : + { + "name" : "Windows", + "version" : "8.1" + } + }, + { + "desc" : "iTunes on Windows 10", + "ua" : "iTunes/12.9.1 (Windows; Microsoft Windows 10 x64 Professional Edition (Build 18362); x64) AppleWebKit/7606.2104.0.21", + "expect" : + { + "name" : "Windows", + "version" : "10" + } + }, + { + "desc" : "iTunes on Windows 10", + "ua" : "iTunes/12.6.3 (Windows; Microsoft Windows 10.0 x64 (Build 17763); x64) AppleWebKit/7604.1038.1006.6", + "expect" : + { + "name" : "Windows", + "version" : "10" + } + }, + { + "desc" : "iTunes on Windows 10 S", + "ua" : "iTunes/12.12 (Windows; Microsoft Windows 10 S x64; x64) AppleWebKit/7613.2007", + "expect" : + { + "name" : "Windows", + "version" : "10" + } + }, + { + "desc" : "iTunes on Windows 11", + "ua" : "iTunes/12.13 (Windows; Microsoft Windows 11 x64; x64) AppleWebKit/7613.2007", + "expect" : + { + "name" : "Windows", + "version" : "11" + } } ] \ No newline at end of file diff --git a/test/data/ua/os/xubuntu.json b/test/data/ua/os/xubuntu.json new file mode 100644 index 0000000..1f38a96 --- /dev/null +++ b/test/data/ua/os/xubuntu.json @@ -0,0 +1,20 @@ +[ + { + "desc" : "Xubuntu", + "ua" : "Mozilla/5.0 (X11; Xubuntu Linux 21.10 x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.81 Safari/537.57 Vivaldi/5.1.2 (Blink)", + "expect" : + { + "name" : "Xubuntu", + "version" : "21.10" + } + }, + { + "desc" : "Xubuntu", + "ua" : "Mozilla/5.0 (X11; Xubuntu 14.04.5 LTS) AppleWebKit/537.36 (KHTML, like Gecko) Xubuntu Chrome/66.0.2623.87 Safari/537.36", + "expect" : + { + "name" : "Xubuntu", + "version" : "14.04.5" + } + } +] \ No newline at end of file diff --git a/test/data/ua/os/zenwalk.json b/test/data/ua/os/zenwalk.json index 230b5dd..170db50 100644 --- a/test/data/ua/os/zenwalk.json +++ b/test/data/ua/os/zenwalk.json @@ -7,5 +7,14 @@ "name" : "Zenwalk", "version" : "7.3" } + }, + { + "desc" : "Zenwalk", + "ua" : "Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.2.13) Gecko/20101221 IceCat/3.6.13 (like Firefox/3.6.13) (Zenwalk GNU Linux)", + "expect" : + { + "name" : "Zenwalk", + "version" : "undefined" + } } ] \ No newline at end of file diff --git a/test/unit/ua-ch.js b/test/unit/ua-ch.js index 54e2f9a..7d12d50 100644 --- a/test/unit/ua-ch.js +++ b/test/unit/ua-ch.js @@ -313,6 +313,19 @@ describe('UA-CH Headers tests', () => { } } }, + { + headers : { + 'sec-ch-ua': '" Not;A Brand";v="99", "Microsoft Edge";v="103", "Chromium";v="103", "Microsoft Edge WebView2";v="104"' + }, + expect: { + browser : { + name : 'Edge WebView2', + version : '104', + major : '104', + type : undefined + } + } + }, { headers : { 'sec-ch-ua': '"Not.A/Brand";v="8", "Chromium";v="114", "HuaweiBrowser";v="114"' @@ -470,7 +483,7 @@ describe('Identify vendor & type of device from given model name', () => { { model: 'CPH2389', expect: { - vendor : 'OPPO', + vendor : 'OnePlus', type : 'mobile' } },