Skip to content

Commit

Permalink
feat(sync) Improves version detection for Windows (matomo-org#7868)
Browse files Browse the repository at this point in the history
---
feat(sync) Improves engine detection for Pluma (matomo-org#7866)
---
feat(sync) Adds detection for Adobe Acrobat Reader and improves detection for various apps (matomo-org#7867)
* Improves detection for Visual Studio Code
* Improves detection for GitHub Desktop
* Improves detection for Adobe NGL
* Adds detection for Adobe Acrobat Reader
* Adds detection for Fiddler Classic
* Move ZEIT ONLINE before generic
* Add website for Ehlel
---
feat(sync) Adds detection for TracePal and TopSecret Chat (matomo-org#7871)
* Adds detection for TracePal
* Adds detection for TopSecret Chat
---
feat(sync) Adds detection for CloudServerMarketSpider and Pandalytics (matomo-org#7873)
* Adds detection for Pandalytics
* Adds detection for CloudServerMarketSpider
---
feat(sync) Improves version detection for iOS and macOS (matomo-org#7878)
---
feat(sync) Improves version detection for Windows client hints (matomo-org#7876)
---
feat(sync) Adds detection for Whale TV Browser, Cultraview, evvoli and Top-Tech brands, improves detection for various brands (matomo-org#7881)
* Improves detection for Thomson devices
* Improves detection for Miray devices
* Improves detection for Essentielb devices
* Improves detection for Manta Multimedia devices
* Improves detection for Master-G devices
* Adds detection for evvoli brand
* Improves detection for AOC devices
* Improves detection for Philips devices
* Improves detection for Whale OS
* Improves detection for TCL devices
* Improves detection for SCBC devices
* Adds detection for WhaleBrowser
* Improves detection for Skyworth devices
* Adds detection for Top-Tech brand
* Adds detection for Cultraview brand
* Rename TCL to TCL SCBC
* Rename WhaleBrowser to Whale TV Browser
---
feat(sync) Improves version detection for Fire OS from client hints (matomo-org#7884)
---
feat(sync) Improves version detection for Lineage OS (matomo-org#7893)
---
feat(sync) Improves detection for Fire TV devices (matomo-org#7891)
---
feat(sync) Improves version detection for webOS (matomo-org#7887)
---
feat(sync) Improves version detection for Blink engine (matomo-org#7892)
---
feat(sync) Detect new brand AZOM and Detect devices for exist brands (matomo-org#7894)
feat(device) detect brand Realme: V60s (RMX3996), C63 5G (RMX3950)
feat(device) detect brand Nubia: Focus 5G (Z2357N), Music (Z2353)
feat(device) detect brand Symphony: Innova 30, Innova 20
feat(device) detect brand T-Mobile: REVVL Tab 5G (TMRV5GTB)
feat(device) detect brand Vorcom: Ultra Pad
feat(device) detect brand Samsung: Galaxy M35 5G (SM-M356B), Galaxy A54 5G (SM-S546VL)
feat(device) detect new brand AZOM: River 1
feat(device) detect brand Sharp: Aquos V6 5G (SH-C05)
feat(device) detect brand Cherry Mobile: Aqua S10 Pro
feat(device) detect brand Tecno Mobile: Spark 8C (TECNO KG5k)
---
feat(sync) Improves detection for LG, ONVO and Qilive devices (matomo-org#7888)
* Improves detection for ONVO devices
* Improves detection for Qilive devices
* Improves model detection for unknown brands
* Improves detection for LG devices
* Fix webOS version in tests
* Improve regex from LG matrix
---
feat(sync) Improves engine version detection for Blink (matomo-org#7895)
---
feat(sync) Adds detection for Singlebox and improves detection for Skye (matomo-org#7899)
* Improves detection for Skye
* Adds detection for Singlebox
---
feat(sync) Improves detection for quic-go (matomo-org#7904)
---
feat(sync) Detect new brand DUDU AUTO and Detect devices for exist brands (matomo-org#7905)
feat(device) detect new brand DUDU AUTO: DUDU7
feat(device) detect brand Tecno Mobile: Camon 30S Pro (TECNO CLA6), Camon 30S (TECNO CLA5)
feat(device) detect brand Sagemcom: DCTIW362 Play
feat(device) detect brand Asano: 28LH8120T, 28LH8110T
feat(device) detect brand Yandex: YNDX-00076, YNDX-00074
feat(device) detect brand KENSHI: K10
feat(device) detect brand W&O: WO Pad Max
---
feat(sync) Improves detection for Lectrus, Maxcom and Sunmax devices (matomo-org#7906)
* Improves detection for Sunmax devices
* Improves detection for Maxcom devices
* Improves detection for Lectrus devices
---
feat(sync) Rename Arc to Arc Search and improves detection for Arc Search and Chrome Webview (matomo-org#7908)
* Rename Arc to Arc Search
* Improves detection for Arc Search
* Improves detection for Chrome Webview
---
feat(sync) Improves detection for Edenwood, Infomir, Hisense and Salora devices (matomo-org#7907)
* Improves detection for Infomir devices
* Improves detection for Hisense devices
* Improves detection for Edenwood devices
* Improves detection for Salora devices
  • Loading branch information
sanchezzzhak committed Nov 15, 2024
1 parent 4740387 commit 39de41d
Show file tree
Hide file tree
Showing 44 changed files with 7,963 additions and 4,642 deletions.
60 changes: 12 additions & 48 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ const DEVICE_PARSER_LIST = require('./parser/const/device-parser');
const CLIENT_PARSER_LIST = require('./parser/const/client-parser');
const FORM_FACTORS_MAPPING = require('./parser/const/form-factor-mapping');
const MOBILE_BROWSER_LIST = require('./parser/client/browser-short-mobile');
const { hasUserAgentClientHintsFragment, hasDeviceModelByClientHints } = require('./parser/helper');
const VENDOR_FRAGMENT_PARSER = 'VendorFragment';
const OS_PARSER = 'Os';
const BOT_PARSER = 'Bot';
Expand Down Expand Up @@ -696,46 +695,13 @@ class DeviceDetector {
return aliasDevice.parse(userAgent);
}

/**
* restore original userAgent from clientHints object
* @param {string} userAgent
* @param {ResultClientHints} clientHints
*/
restoreUserAgentFromClientHints(
userAgent,
clientHints
) {
if (!helper.hasDeviceModelByClientHints(clientHints)) {
return userAgent;
}

const deviceModel = clientHints.device.model;

if (deviceModel !== '' && helper.hasUserAgentClientHintsFragment(userAgent)) {
const osHints = attr(clientHints, 'os', {});
const osVersion = attr(osHints, 'version', '');
return userAgent.replace(/(Android (?:10[.\d]*; K|1[1-5]))/,
`Android ${osVersion !== '' ? osVersion : '10'}; ${deviceModel}`
);
}

if (deviceModel !== '' && helper.hasDesktopFragment(userAgent)) {
return userAgent.replace(/(X11; Linux x86_64)/,
`X11; Linux x86_64; ${deviceModel}`
);
}

return userAgent;
}

/**
* parse device
* @param {string} userAgent
* @param {ResultClientHints} clientHints
* @return {ResultDevice}
*/
parseDevice(userAgent, clientHints) {
let ua = this.restoreUserAgentFromClientHints(userAgent, clientHints);
let brandIndexes = [];

let result = {
Expand All @@ -748,6 +714,7 @@ class DeviceDetector {
trusted: null
};

let ua = helper.restoreUserAgentFromClientHints(userAgent, clientHints);
// skip all parse is client-hints useragent and model not exist
if (!helper.hasDeviceModelByClientHints(clientHints) && helper.hasUserAgentClientHintsFragment(userAgent)) {
return Object.assign({}, result);
Expand Down Expand Up @@ -805,8 +772,7 @@ class DeviceDetector {
* @return {ResultVendor|null}
*/
parseVendor(userAgent) {
let parser = this.getParseVendor(VENDOR_FRAGMENT_PARSER);
return parser.parse(userAgent);
return this.getParseVendor(VENDOR_FRAGMENT_PARSER).parse(userAgent);
}

/**
Expand All @@ -823,8 +789,7 @@ class DeviceDetector {
}

for (let name in this.botParserList) {
let parser = this.botParserList[name];
let resultMerge = parser.parse(userAgent);
let resultMerge = this.botParserList[name].parse(userAgent);
if (resultMerge) {
result = Object.assign(result, resultMerge);
break;
Expand All @@ -842,19 +807,19 @@ class DeviceDetector {
parseClient(userAgent, clientHints) {
const extendParsers = [CLIENT_PARSER_LIST.MOBILE_APP, CLIENT_PARSER_LIST.BROWSER];
for (let name in this.clientParserList) {
let parser = this.clientParserList[name];

if (this.clientIndexes && extendParsers.includes(name)) {
let hash = parser.parseFromHashHintsApp(clientHints);
let hint = parser.parseFromClientHints(clientHints);
let data = parser.parseUserAgentByPositions(userAgent);
let result = parser.prepareParseResult(userAgent, data, hint, hash);
if (result !== null && result.name) {
const parser = this.clientParserList[name];

if (this.clientIndexes && extendParsers.includes(name) && userAgent) {
const hash = parser.parseFromHashHintsApp(clientHints);
const hint = parser.parseFromClientHints(clientHints);
const data = parser.parseUserAgentByPositions(userAgent);
const result = parser.prepareParseResult(userAgent, data, hint, hash);
if (result && result.name) {
return Object.assign({}, result);
}
}

let result = parser.parse(userAgent, clientHints);
const result = parser.parse(userAgent, clientHints);
if (result && result.name) {
return Object.assign({}, result);
}
Expand Down Expand Up @@ -897,7 +862,6 @@ class DeviceDetector {

deviceData = Object.assign(deviceData, deviceDataType);


if (this.deviceTrusted) {
deviceData.trusted = DeviceTrusted.check(osData, clientData, deviceData, clientHints);
} else {
Expand Down
3 changes: 2 additions & 1 deletion parser/client-abstract-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,12 @@ class ClientAbstractParser extends ParserAbstract {
return result;
}
}

return null;
}

parseUserAgentByPositions(userAgent) {
let positions = IndexerClient.findClientRegexPositionsForUserAgent(
const positions = IndexerClient.findClientRegexPositionsForUserAgent(
userAgent,
String(this.type),
);
Expand Down
3 changes: 2 additions & 1 deletion parser/client/browser-families.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ module.exports = {
'K4', 'WK', 'T3', 'K5', 'MU', '9P', 'K6', 'VR', 'N9',
'M9', 'F9', '0P', '0A', 'JR', 'D3', 'TK', 'BP', '2F',
'2M', 'K7', '1N', '8A', 'H7', 'X3', 'T4', 'X4', '5O',
'8C', '3M', '6I', '2P', 'PU', '7I', 'X5', 'AL',
'8C', '3M', '6I', '2P', 'PU', '7I', 'X5', 'AL', '3P',
'W2', 'ZB',
],
'Firefox': [
'FF', 'BI', 'BF', 'BH', 'BN', 'C0', 'CU', 'EI', 'F1',
Expand Down
2 changes: 1 addition & 1 deletion parser/client/browser-short-mobile.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ module.exports = [
'DP', 'KL', 'K4', 'N6', 'KU', 'WK', 'M8', 'UP', 'ZT',
'9P', 'N8', 'VR', 'N9', 'M9', 'F9', '0P', '0A', '2F',
'2M', 'K7', '1N', '8A', 'H7', 'X3', 'X4', '5O', '6I',
'7I', 'X5',
'7I', 'X5', '3P',

];
4 changes: 3 additions & 1 deletion parser/client/browser-short.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ module.exports = {
'AW': 'Amiga Aweb',
'PN': 'APN Browser',
'6A': 'Arachne',
'RA': 'Arc',
'RA': 'Arc Search',
'R5': 'Armorfly Browser',
'AI': 'Arvin',
'AK': 'Ask.com',
Expand Down Expand Up @@ -531,6 +531,7 @@ module.exports = {
'K1': 'Sidekick',
'S1': 'SimpleBrowser',
'3S': 'SilverMob US',
'ZB': 'Singlebox',
'SY': 'Sizzy',
'K3': 'Skye',
'SK': 'Skyfire',
Expand Down Expand Up @@ -638,6 +639,7 @@ module.exports = {
'WB': 'Wave Browser',
'WA': 'Wavebox',
'WH': 'Whale Browser',
'W2': 'Whale TV Browser',
'WO': 'wOSBrowser',
'3W': 'w3m',
'WT': 'WeTab Browser',
Expand Down
82 changes: 41 additions & 41 deletions parser/client/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ class Browser extends ClientAbstractParser {
/**
* Generates the result for the parse method
*
* @param userAgent
* @param data
* @param hint
* @param hash
* @returns {null|{engine: string, name: string, short_name: string, type: string, engine_version: string, family: string, version: string}}
* @param {string} userAgent
* @param {{}} data
* @param {{}} hint
* @param {{}} hash
* @returns {null|ResultClient}
*/
prepareParseResult(
userAgent,
Expand All @@ -78,24 +78,23 @@ class Browser extends ClientAbstractParser {
let engineVersion = '';
let short = '';
let family = '';
// client-hint+user-agent

// use client hints in favor of user agent data if possible
if (hint && hint.name && hint.version) {
name = hint.name;
version = hint.version;
short = hint.short_name;
family = this.buildFamily(short);

if (data) {
// If the version reported from the client hints is YYYY or YYYY.MM (e.g., 2022 or 2022.04),
// then it is the Iridium browser
// https://iridiumbrowser.de/news/
if (/^202[0-4]/.test(version)) {
name = 'Iridium';
short = 'I1';
engine = data.engine;
engineVersion = data.engine_version;
}
// If the version reported from the client hints is YYYY or YYYY.MM (e.g., 2022 or 2022.04),
// then it is the Iridium browser
// https://iridiumbrowser.de/news/
if (/^202[0-4]/.test(version)) {
name = 'Iridium';
short = 'I1';
}

if (data) {
// https://bbs.360.cn/thread-16096544-1-1.html
if (/^15/.test(version) && /^114/.test(data.version)) {
name = '360 Secure Browser';
Expand All @@ -113,13 +112,10 @@ class Browser extends ClientAbstractParser {
engine = data.engine;
engineVersion = data.engine_version;
}

// If client hints report Chromium, but user agent detects a Chromium based browser, we favor this instead
if (
('Chromium' === name || 'Chrome Webview' === name) &&
data.name !== ''&&
['CR', 'CV', 'AN'].indexOf(data.short_name) === -1
) {
const hasChromeBased = ('Chromium' === name || 'Chrome Webview' === name) && data.name
&& ['CR', 'CV', 'AN'].indexOf(data.short_name) === -1;
if (hasChromeBased) {
name = data.name;
short = data.short_name;
version = data.version;
Expand All @@ -144,22 +140,30 @@ class Browser extends ClientAbstractParser {
if (data.version && data.version.indexOf(version) === 0 && helper.versionCompare(version, data.version) < 0) {
version = data.version;
}
// If DDG Private browser then set version empty string
if ('DuckDuckGo Privacy Browser' === name) {
version = '';
}
}


// If DDG Private browser then set version empty string
if ('DuckDuckGo Privacy Browser' === name) {
version = '';
}

// In case client hints report a more detailed engine version, we try to use this instead
if ('Blink' === engine && 'Iridium' !== name && helper.versionCompare(engineVersion, hint.version) < 0) {
engineVersion = hint.version;
}

} else if (data !== null) {
name = data.name;
version = data.version;
short = data.short_name;
engine = data.engine;
engineVersion = data.engine_version;

}

family = this.buildFamily(short);

// is app id
if (hash !== null && name !== hash.name) {
name = hash.name;
version = '';
Expand Down Expand Up @@ -198,10 +202,6 @@ class Browser extends ClientAbstractParser {
}
}

if (name === '') {
return null;
}

return {
type: String(type),
name: String(name),
Expand All @@ -217,22 +217,22 @@ class Browser extends ClientAbstractParser {
* General method for parsing user-agent and client-hints
*
* @param {string} userAgent
* @param {*} clientHints
* @returns {{engine: string, name: (string|*), short_name: string, type: string, engine_version: string, family: (string|string), version: string}|null}
* @param {} clientHints
* @returns {ResultClient|null}
*/
parse(userAgent, clientHints) {
userAgent = this.prepareUserAgent(userAgent);
const hash = this.parseFromHashHintsApp(clientHints);
const hint = this.parseFromClientHints(clientHints);
const data = this.parseFromUserAgent(userAgent);
const data = this.parseFromUserAgent(userAgent, clientHints);
return this.prepareParseResult(userAgent, data, hint, hash);
}

/**
* Parses client-hints for getting the browser name from the application ID (clientHints.app)
*
* @param {*} clientHints
* @return {{name: *}}
* @param {ResultClientHints} clientHints
* @return {{name: string}}
*/
parseFromHashHintsApp(clientHints) {
return browserHints.parse(clientHints);
Expand All @@ -241,7 +241,7 @@ class Browser extends ClientAbstractParser {
/**
* Parses client-hints for getting browser name, version, short name
*
* @param {*} clientHints
* @param {ResultClientHints} clientHints
* @return {{name: string, short_name: string, version: string}}
*/
parseFromClientHints(clientHints) {
Expand All @@ -250,7 +250,7 @@ class Browser extends ClientAbstractParser {
let version = '';

if (clientHints && clientHints.client) {
let brands = ArrayPath.get(clientHints, 'client.brands', []);
const brands = ArrayPath.get(clientHints, 'client.brands', []);
for (let brandItem of brands) {
let brand = compareBrandForClientHints(brandItem.brand);
for (let browserName in this.getCollectionBrowsers()) {
Expand Down Expand Up @@ -283,7 +283,7 @@ class Browser extends ClientAbstractParser {
return {
name: name,
short_name: short,
version: version
version: this.buildVersion(version, [])
};
}

Expand Down Expand Up @@ -465,7 +465,7 @@ class Browser extends ClientAbstractParser {
let engineToken = '' + engine;

if ('Blink' === engine) {
engineToken = 'Chr[o0]me|Cronet';
engineToken = 'Chr[o0]me|Chromium|Cronet';
}

if ('LibWeb' === engine) {
Expand All @@ -478,7 +478,7 @@ class Browser extends ClientAbstractParser {

let regexp = new RegExp(
'(?:' + engineToken + ')' +
'\\s*\\/?\\s*(((?=\\d+\\.\\d)\\d+[.\\d]*|\\d{1,7}(?=(?:\\D|$))))',
'\\s*[/_]?\\s*(((?=\\d+\\.\\d)\\d+[.\\d]*|\\d{1,7}(?=(?:\\D|$))))',
'i'
);

Expand Down
10 changes: 5 additions & 5 deletions parser/client/mobile-app.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ class MobileApp extends ClientAbstractParser {
}

parseFromClientHints(clientHints) {
let name = '';
let version = '';
const name = '';
const version = '';
return {name, version}
}

Expand Down Expand Up @@ -56,9 +56,9 @@ class MobileApp extends ClientAbstractParser {
* @returns {({name: string, type: string, version: string})|null}
*/
parse(userAgent, clientHints) {
let hash = this.parseFromHashHintsApp(clientHints);
let hint = this.parseFromClientHints(clientHints);
let data = super.parse(userAgent, clientHints);
const hash = this.parseFromHashHintsApp(clientHints);
const hint = this.parseFromClientHints(clientHints);
const data = super.parse(userAgent, clientHints);
return this.prepareParseResult(userAgent, data, hint, hash);
}
}
Expand Down
Loading

0 comments on commit 39de41d

Please sign in to comment.