63 lines
1.9 KiB
JavaScript
63 lines
1.9 KiB
JavaScript
// Guest-only fingerprinting module
|
|
// Only guests are fingerprinted - registered users are NOT fingerprinted for privacy
|
|
import { browser } from '$app/environment';
|
|
|
|
let cachedFingerprint = null;
|
|
let fingerprintPromise = null;
|
|
|
|
export async function getGuestFingerprint() {
|
|
if (!browser) return null;
|
|
|
|
// Return cached fingerprint if available
|
|
if (cachedFingerprint) return cachedFingerprint;
|
|
|
|
// Return existing promise if fingerprint is being generated
|
|
if (fingerprintPromise) return fingerprintPromise;
|
|
|
|
fingerprintPromise = generateFingerprint();
|
|
cachedFingerprint = await fingerprintPromise;
|
|
fingerprintPromise = null;
|
|
|
|
return cachedFingerprint;
|
|
}
|
|
|
|
async function generateFingerprint() {
|
|
try {
|
|
const FingerprintJS = await import('@fingerprintjs/fingerprintjs');
|
|
const fp = await FingerprintJS.load();
|
|
const result = await fp.get();
|
|
return result.visitorId;
|
|
} catch (error) {
|
|
console.error('Failed to generate fingerprint:', error);
|
|
// Fallback: generate a simple fingerprint from available data
|
|
return generateFallbackFingerprint();
|
|
}
|
|
}
|
|
|
|
function generateFallbackFingerprint() {
|
|
// Fallback fingerprint using basic browser data
|
|
const data = [
|
|
navigator.userAgent,
|
|
navigator.language,
|
|
screen.width + 'x' + screen.height,
|
|
screen.colorDepth,
|
|
new Date().getTimezoneOffset(),
|
|
navigator.hardwareConcurrency || 0,
|
|
navigator.deviceMemory || 0
|
|
].join('|');
|
|
|
|
// Simple hash function
|
|
let hash = 0;
|
|
for (let i = 0; i < data.length; i++) {
|
|
const char = data.charCodeAt(i);
|
|
hash = ((hash << 5) - hash) + char;
|
|
hash = hash & hash;
|
|
}
|
|
return 'fallback_' + Math.abs(hash).toString(36);
|
|
}
|
|
|
|
// Clear cached fingerprint (useful for testing)
|
|
export function clearCachedFingerprint() {
|
|
cachedFingerprint = null;
|
|
fingerprintPromise = null;
|
|
}
|