73 lines
2.1 KiB
JavaScript
73 lines
2.1 KiB
JavaScript
'use strict';
|
|
|
|
const crypto = require('crypto');
|
|
|
|
function parseBrowser(userAgent) {
|
|
const ua = String(userAgent || '');
|
|
if (/Edg\//i.test(ua)) return 'Edge';
|
|
if (/OPR\//i.test(ua) || /Opera/i.test(ua)) return 'Opera';
|
|
if (/Firefox\//i.test(ua)) return 'Firefox';
|
|
if (/Chrome\//i.test(ua) || /CriOS\//i.test(ua)) return 'Chrome';
|
|
if (/Safari\//i.test(ua)) return 'Safari';
|
|
if (/curl\//i.test(ua)) return 'curl';
|
|
if (/PostmanRuntime\//i.test(ua)) return 'Postman';
|
|
return 'Unknown';
|
|
}
|
|
|
|
function parseOs(userAgent) {
|
|
const ua = String(userAgent || '');
|
|
if (/iPhone|iPad|iPod/i.test(ua)) return 'iOS';
|
|
if (/Android/i.test(ua)) return 'Android';
|
|
if (/Windows NT/i.test(ua)) return 'Windows';
|
|
if (/Mac OS X|Macintosh/i.test(ua)) return 'macOS';
|
|
if (/Linux/i.test(ua)) return 'Linux';
|
|
if (/CrOS/i.test(ua)) return 'ChromeOS';
|
|
return 'Unknown';
|
|
}
|
|
|
|
function parseDeviceType(userAgent) {
|
|
const ua = String(userAgent || '');
|
|
if (/iPad|Tablet/i.test(ua)) return 'tablet';
|
|
if (/Mobi|iPhone|Android/i.test(ua)) return 'mobile';
|
|
if (/curl|PostmanRuntime/i.test(ua)) return 'api';
|
|
return 'desktop';
|
|
}
|
|
|
|
function coarseIpPrefix(ipAddress) {
|
|
const ip = String(ipAddress || '').trim();
|
|
if (!ip) return '';
|
|
|
|
const v4 = ip.match(/(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.\d{1,3}$/);
|
|
if (v4) return `${v4[1]}.${v4[2]}.${v4[3]}.0/24`;
|
|
|
|
if (ip.includes(':')) {
|
|
return `${ip.split(':').slice(0, 4).join(':')}::/64`;
|
|
}
|
|
|
|
return ip;
|
|
}
|
|
|
|
function buildDeviceFingerprint({ userAgent, ipAddress }) {
|
|
const browser = parseBrowser(userAgent);
|
|
const os = parseOs(userAgent);
|
|
const deviceType = parseDeviceType(userAgent);
|
|
const ipPrefix = coarseIpPrefix(ipAddress);
|
|
const source = [browser, os, deviceType, String(userAgent || '').slice(0, 500), ipPrefix].join('|');
|
|
const fingerprint = crypto.createHash('sha256').update(source).digest('hex').slice(0, 16);
|
|
|
|
return {
|
|
browser,
|
|
os,
|
|
device_type: deviceType,
|
|
device_fingerprint: fingerprint,
|
|
};
|
|
}
|
|
|
|
module.exports = {
|
|
buildDeviceFingerprint,
|
|
coarseIpPrefix,
|
|
parseBrowser,
|
|
parseDeviceType,
|
|
parseOs,
|
|
};
|