// Утилиты для получения названия ASN с кэшем в localStorage const CACHE_KEY = 'asnNameCache.v1'; const DEFAULT_TTL_MS = 30 * 24 * 60 * 60 * 1000; // 30 дней function readCache() { try { const raw = localStorage.getItem(CACHE_KEY); if (!raw) return {}; const data = JSON.parse(raw); return typeof data === 'object' && data ? data : {}; } catch { return {}; } } function writeCache(cache) { try { localStorage.setItem(CACHE_KEY, JSON.stringify(cache)); } catch { /* no-op */ } } function getCached(asn) { const cache = readCache(); const entry = cache[String(asn)]; if (!entry) return null; if (Date.now() > (entry.ts || 0)) return null; return entry.name || null; } function setCached(asn, name, ttlMs = DEFAULT_TTL_MS) { const cache = readCache(); cache[String(asn)] = { name: String(name || '').trim(), ts: Date.now() + ttlMs }; writeCache(cache); } async function fetchFromBGPView(asn) { try { const url = `https://api.bgpview.io/asn/AS${asn}`; const res = await fetch(url, { method: 'GET' }); if (!res.ok) throw new Error(`HTTP ${res.status}`); const json = await res.json(); const name = json?.data?.name || json?.data?.description || ''; return String(name || '').trim() || null; } catch { return null; } } async function fetchFromRIPE(asn) { try { const url = `https://stat.ripe.net/data/as-overview/data.json?resource=AS${asn}`; const res = await fetch(url, { method: 'GET' }); if (!res.ok) throw new Error(`HTTP ${res.status}`); const json = await res.json(); const name = json?.data?.holder || json?.data?.name || ''; return String(name || '').trim() || null; } catch { return null; } } export async function getAsnName(asn, { ttlMs = DEFAULT_TTL_MS } = {}) { const key = String(asn).trim(); if (!/^[0-9]+$/.test(key)) return null; const cached = getCached(key); if (cached) return cached; // попытаемся получить из провайдеров const providers = [fetchFromBGPView, fetchFromRIPE]; for (const p of providers) { const name = await p(key); if (name) { setCached(key, name, ttlMs); return name; } } // Закэшируем пустой ответ на короткое время, чтобы не долбить API setCached(key, '', 60 * 60 * 1000); // 1 час return null; } export function getAsnNameSync(asn) { return getCached(asn); }