/* =================================================== JAESWIFT.XYZ — Scan The Visitor Typewriter-animated visitor recon overlay. =================================================== */ (function () { 'use strict'; const DISMISS_KEY = 'scanDismissed'; const DISMISS_DAYS = 7; const BADGE_HIDE_KEY = 'scanBadgeHidden'; const TYPE_SPEED = 22; // ms per char const LINE_PAUSE = 120; // ─── Check if dismissed recently ──────────────── function isDismissed() { try { const raw = localStorage.getItem(DISMISS_KEY); if (!raw) return false; const ts = parseInt(raw, 10); if (!ts) return false; const ageDays = (Date.now() - ts) / (1000 * 60 * 60 * 24); return ageDays < DISMISS_DAYS; } catch (e) { return false; } } function setDismissed() { try { localStorage.setItem(DISMISS_KEY, Date.now().toString()); } catch (e) {} } function isBadgeHidden() { try { return localStorage.getItem(BADGE_HIDE_KEY) === '1'; } catch (e) { return false; } } // ─── Gather local client info ─────────────────── function localInfo() { const scr = `${screen.width}x${screen.height}`; const dpr = (window.devicePixelRatio || 1); let conn = 'Unknown'; try { const c = navigator.connection || navigator.mozConnection || navigator.webkitConnection; if (c) { const t = c.effectiveType || c.type || ''; conn = t ? t.toUpperCase() : 'Unknown'; if (c.downlink) conn += `, ${c.downlink}Mbps`; if (c.rtt) conn += `, ${c.rtt}ms`; } } catch (e) {} return { screen: `${scr} @ ${dpr}x`, connection: conn, tz: Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC', lang: navigator.language || 'en', }; } // ─── Build scan lines list ────────────────────── function buildLines(data, local) { const locStr = data.city ? `${data.city}, ${data.country}` : data.country; const browser = data.browser + (data.browser_version ? ' ' + data.browser_version : ''); const osStr = data.os + (data.os_version ? ' ' + data.os_version : ''); const flag = data.country_flag || ''; const threatColor = data.threat_level === 'GREEN' ? 'green' : data.threat_level === 'AMBER' ? 'amber' : 'red'; const bar = (() => { if (data.threat_level === 'GREEN') return '[█░░░░] GREEN — TRUSTED'; if (data.threat_level === 'AMBER') return '[███░░] AMBER — MONITORED'; if (data.threat_level === 'RED') return '[█████] RED — BLOCKED'; return '[░░░░░] UNKNOWN'; })(); return [ { cls: 'green', text: '>>> ESTABLISHING SECURE CONNECTION...' }, { cls: 'green', text: '>>> HANDSHAKE OK · TLS 1.3 · AES-256-GCM' }, { cls: 'green', text: '>>> SCANNING OPERATOR...' }, { cls: 'dim', text: '' }, { cls: 'green', text: `>>> IP ADDRESS....... ${data.ip_masked}` }, { cls: 'green', text: `>>> GEOLOCATION...... ${locStr} ${flag}` }, { cls: 'green', text: `>>> NETWORK.......... ${data.isp}` }, data.hostname ? { cls: 'dim', text: `>>> HOSTNAME......... ${data.hostname}` } : null, { cls: 'green', text: `>>> BROWSER.......... ${browser}` }, { cls: 'green', text: `>>> OS............... ${osStr}` }, { cls: 'green', text: `>>> DEVICE........... ${data.device}` }, { cls: 'green', text: `>>> SCREEN........... ${local.screen}` }, { cls: 'green', text: `>>> LANGUAGE......... ${local.lang}` }, { cls: 'green', text: `>>> TIMEZONE......... ${local.tz}` }, { cls: 'green', text: `>>> CONNECTION....... ${local.connection}` }, { cls: 'dim', text: '' }, { cls: threatColor, text: `>>> THREAT LEVEL..... ${bar}` }, { cls: threatColor, text: `>>> STATUS........... ${data.threat_reason}` }, { cls: 'dim', text: '' }, { cls: 'green', text: '>>> ACCESS GRANTED — WELCOME, OPERATOR' }, ].filter(Boolean); } // ─── Typewriter: types text into element ───────── function typeInto(el, text, speed) { return new Promise(function (resolve) { let i = 0; function tick() { if (i < text.length) { el.textContent += text.charAt(i); i++; setTimeout(tick, speed); } else { resolve(); } } if (!text.length) { resolve(); return; } tick(); }); } // ─── Build overlay DOM ─────────────────────────── function buildOverlay() { const overlay = document.createElement('div'); overlay.className = 'scan-overlay'; overlay.id = 'scanOverlay'; overlay.innerHTML = ` `; return overlay; } // ─── Build badge (collapsed state) ─────────────── function buildBadge(data) { const flag = data.country_flag || '🌐'; const cc = data.country_code || 'XX'; const locShort = data.city ? `${data.city}, ${cc}` : (data.country || cc); const badge = document.createElement('div'); badge.className = 'scan-badge'; badge.id = 'scanBadge'; badge.title = 'Click to re-run scan'; badge.innerHTML = ` ${flag}
OPERATOR ${locShort}
`; badge.addEventListener('click', function (e) { if (e.target && e.target.id === 'scanBadgeClose') return; // Re-run scan on click try { localStorage.removeItem(DISMISS_KEY); } catch (err) {} badge.remove(); runScan(); }); badge.querySelector('#scanBadgeClose').addEventListener('click', function (e) { e.stopPropagation(); try { localStorage.setItem(BADGE_HIDE_KEY, '1'); } catch (err) {} badge.classList.add('scan-closing'); setTimeout(() => badge.remove(), 220); }); document.body.appendChild(badge); } // ─── Render scan lines one-by-one ──────────────── async function renderLines(body, lines) { for (let i = 0; i < lines.length; i++) { const item = lines[i]; const span = document.createElement('span'); span.className = `scan-line scan-line-${item.cls}`; body.appendChild(span); if (item.text) { await typeInto(span, item.text, TYPE_SPEED); body.scrollTop = body.scrollHeight; } else { span.textContent = '\u00A0'; } await new Promise(r => setTimeout(r, LINE_PAUSE)); } } // ─── Run full scan sequence ────────────────────── async function runScan() { // fade in overlay first with 'CONNECTING...' const overlay = buildOverlay(); document.body.appendChild(overlay); const body = overlay.querySelector('#scanBody'); const statusEl = overlay.querySelector('#scanStatus'); const closeBtn = overlay.querySelector('#scanClose'); const dismissBtn = overlay.querySelector('#scanDismissBtn'); const ackBtn = overlay.querySelector('#scanAcceptBtn'); let scanData = null; let apiFailed = false; // Seed initial connecting line before fetch completes const initLine = document.createElement('span'); initLine.className = 'scan-line scan-line-green'; body.appendChild(initLine); typeInto(initLine, '>>> INITIALISING RECON PROTOCOL...', TYPE_SPEED); function closeAll(dismiss) { overlay.classList.add('scan-closing'); if (dismiss) setDismissed(); setTimeout(() => { overlay.remove(); if (scanData && !isBadgeHidden()) { buildBadge(scanData); } }, 260); } closeBtn.addEventListener('click', () => closeAll(false)); dismissBtn.addEventListener('click', () => closeAll(true)); ackBtn.addEventListener('click', () => closeAll(false)); // allow esc to close function escHandler(e) { if (e.key === 'Escape') { closeAll(false); document.removeEventListener('keydown', escHandler); } } document.addEventListener('keydown', escHandler); try { const r = await fetch('/api/visitor/scan', { credentials: 'same-origin' }); if (r.ok) { scanData = await r.json(); } else if (r.status === 429) { apiFailed = true; } else { apiFailed = true; } } catch (e) { apiFailed = true; } // clear init line body.innerHTML = ''; if (apiFailed || !scanData) { const errSpan = document.createElement('span'); errSpan.className = 'scan-line scan-line-red'; body.appendChild(errSpan); await typeInto(errSpan, '>>> RECON SERVICE UNAVAILABLE — STANDBY', TYPE_SPEED); statusEl.textContent = '● OFFLINE'; statusEl.style.color = 'var(--danger)'; ackBtn.disabled = false; ackBtn.style.opacity = '1'; ackBtn.style.cursor = 'pointer'; return; } const local = localInfo(); const lines = buildLines(scanData, local); await renderLines(body, lines); statusEl.textContent = '● SCAN COMPLETE'; ackBtn.disabled = false; ackBtn.style.opacity = '1'; ackBtn.style.cursor = 'pointer'; ackBtn.focus(); } // ─── Boot ──────────────────────────────────────── function boot() { if (isDismissed()) { // still show compact badge if not hidden — fetch silently if (!isBadgeHidden()) { fetch('/api/visitor/scan', { credentials: 'same-origin' }) .then(r => r.ok ? r.json() : null) .then(d => { if (d && d.country_code) buildBadge(d); }) .catch(() => {}); } return; } // Slight delay so page renders first setTimeout(runScan, 700); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', boot); } else { boot(); } // Expose for debug / re-trigger window.__jaeScan = { run: runScan, reset: function () { try { localStorage.removeItem(DISMISS_KEY); localStorage.removeItem(BADGE_HIDE_KEY); } catch (e) {} const b = document.getElementById('scanBadge'); if (b) b.remove(); const o = document.getElementById('scanOverlay'); if (o) o.remove(); runScan(); }, }; })();