/* ─── RADAR: Live Intelligence Feed ─────────────── */ (function() { 'use strict'; const API = '/api/radar'; const REFRESH_INTERVAL = 15 * 60 * 1000; // 15 minutes let currentSource = 'all'; let allItems = []; let refreshTimer = null; // ─── Time Ago ────────────────────────────────── function timeAgo(dateStr) { if (!dateStr) return ''; const now = new Date(); const then = new Date(dateStr); const diff = Math.floor((now - then) / 1000); if (diff < 60) return diff + 's ago'; if (diff < 3600) return Math.floor(diff / 60) + 'm ago'; if (diff < 86400) return Math.floor(diff / 3600) + 'h ago'; if (diff < 604800) return Math.floor(diff / 86400) + 'd ago'; return Math.floor(diff / 604800) + 'w ago'; } // ─── Extract Domain ──────────────────────────── function extractDomain(url) { try { const u = new URL(url); return u.hostname.replace('www.', ''); } catch(e) { return ''; } } // ─── Escape HTML ─────────────────────────────── function esc(s) { const d = document.createElement('div'); d.textContent = s; return d.innerHTML; } // ─── Render Feed ─────────────────────────────── function renderFeed(items) { const feed = document.getElementById('radarFeed'); if (!items || items.length === 0) { feed.innerHTML = '
NO SIGNALS DETECTED ON CURRENT FREQUENCY
'; return; } let html = ''; items.forEach(item => { const domain = extractDomain(item.url); const ago = timeAgo(item.published); const sourceClass = 'source-' + item.source_id; const sourceLabel = item.source || 'UNKNOWN'; html += '
'; html += '
' + esc(ago) + '
'; html += '
' + esc(sourceLabel) + '
'; html += '
'; html += ' ' + esc(item.title) + ''; html += '
'; if (domain) { html += ' ' + esc(domain) + ''; } if (item.comments_url) { html += ' COMMENTS'; } html += '
'; html += '
'; html += '
'; }); feed.innerHTML = html; } // ─── Filter & Search ─────────────────────────── function applyFilters() { const q = document.getElementById('radarSearch').value.trim().toLowerCase(); let filtered = allItems; if (currentSource !== 'all') { filtered = filtered.filter(i => i.source_id === currentSource); } if (q) { filtered = filtered.filter(i => (i.title || '').toLowerCase().includes(q) || (i.summary || '').toLowerCase().includes(q) ); } document.getElementById('statTotal').textContent = filtered.length; renderFeed(filtered); } // ─── Fetch Data ──────────────────────────────── async function fetchRadar(forceRefresh) { const feed = document.getElementById('radarFeed'); feed.innerHTML = '
SCANNING FREQUENCIES...
'; try { if (forceRefresh) { await fetch(API + '/refresh', { method: 'POST' }); } const res = await fetch(API); const data = await res.json(); allItems = data.items || []; document.getElementById('statTotal').textContent = allItems.length; // Format last updated if (data.last_updated) { const d = new Date(data.last_updated); const pad = n => String(n).padStart(2, '0'); document.getElementById('statUpdated').textContent = pad(d.getHours()) + ':' + pad(d.getMinutes()) + ':' + pad(d.getSeconds()) + ' UTC'; } applyFilters(); } catch(err) { console.error('RADAR fetch error:', err); feed.innerHTML = '
⚠ SIGNAL LOST — UNABLE TO REACH FEED API
'; } } // ─── Event Listeners ─────────────────────────── function init() { // Source filters document.querySelectorAll('.radar-filter').forEach(btn => { btn.addEventListener('click', function(e) { e.preventDefault(); document.querySelectorAll('.radar-filter').forEach(b => b.classList.remove('active')); this.classList.add('active'); currentSource = this.dataset.source; applyFilters(); }); }); // Search let searchTimeout; document.getElementById('radarSearch').addEventListener('input', function() { clearTimeout(searchTimeout); searchTimeout = setTimeout(applyFilters, 200); }); // Refresh button document.getElementById('radarRefresh').addEventListener('click', function(e) { e.preventDefault(); this.classList.add('spinning'); fetchRadar(true).then(() => { setTimeout(() => this.classList.remove('spinning'), 500); }); }); // Initial fetch fetchRadar(false); // Auto-refresh every 15 min refreshTimer = setInterval(() => fetchRadar(false), REFRESH_INTERVAL); } // ─── Boot ────────────────────────────────────── if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();