194 lines
7.1 KiB
JavaScript

const App = {
myIpMode: false,
submit(event) {
event.preventDefault();
const input = event.target.querySelector('[data-input]');
const host = input.value.trim();
this.check(host);
},
check(host) {
const btn = document.querySelector('[data-submit-btn]');
btn.disabled = true;
this.clearState();
document.querySelector('[data-state="loading"]').hidden = false;
this.myIpMode = host === '';
fetch('/check?host=' + encodeURIComponent(host) + '&format=json')
.then(function(r) {
if (!r.ok) throw new Error('HTTP ' + r.status);
return r.json();
})
.then(function(data) {
document.querySelector('[data-state="loading"]').hidden = true;
document.querySelector('[data-state="result"]').hidden = false;
App.render(data);
window.history.replaceState(null, '', '#/?host=' + encodeURIComponent(data.ip));
})
.catch(function(err) {
document.querySelector('[data-state="loading"]').hidden = true;
document.querySelector('[data-state="error"]').hidden = false;
document.querySelector('[data-error-text]').textContent = err.message;
})
.finally(function() {
btn.disabled = false;
});
},
clearState() {
document.querySelector('[data-state="result"]').hidden = true;
document.querySelector('[data-state="error"]').hidden = true;
document.querySelectorAll('[data-verdict]').forEach(function(el) { el.hidden = true; });
document.querySelectorAll('[data-section]').forEach(function(el) { el.hidden = true; });
document.querySelectorAll('[data-trait]').forEach(function(el) { el.hidden = true; });
document.querySelectorAll('[data-block]').forEach(function(el) { el.hidden = true; });
document.querySelector('[data-resolved-from]').hidden = true;
},
render(data) {
/* ── Verdict ──────────────────────────────────────────── */
document.querySelectorAll('[data-verdict]').forEach(function(el) { el.hidden = true; });
var verdictKey = 'allowed';
if (data.allowlisted) {
verdictKey = 'whitelist';
} else if (data.blocked_inbound && data.blocked_outbound) {
verdictKey = 'blocked-inbound-outbound';
} else if (data.blocked_inbound) {
verdictKey = 'blocked-inbound';
} else if (data.blocked_outbound) {
verdictKey = 'blocked-outbound';
}
document.querySelector('[data-verdict="' + verdictKey + '"]').hidden = false;
/* ── IP address ───────────────────────────────────────── */
document.querySelector('[data-value="ip"]').textContent = data.ip;
/* ── Resolved from ────────────────────────────────────── */
if (data.resolved_from) {
document.querySelector('[data-value="resolved-from"]').textContent = data.resolved_from;
document.querySelector('[data-resolved-from]').hidden = false;
}
/* ── Geo ──────────────────────────────────────────────── */
var geo = data.geo || {};
/* Location */
var locParts = [];
if (geo.city) locParts.push(geo.city);
if (geo.region) {
locParts.push(geo.region + (geo.region_iso ? ' (' + geo.region_iso + ')' : ''));
} else if (geo.region_iso) {
locParts.push(geo.region_iso);
}
if (geo.country) {
locParts.push(geo.country + (geo.country_iso ? ' (' + geo.country_iso + ')' : ''));
}
if (geo.continent) {
locParts.push(geo.continent + (geo.continent_code ? ' (' + geo.continent_code + ')' : ''));
}
if (locParts.length) {
document.querySelector('[data-value="location"]').textContent = locParts.join(', ');
document.querySelector('[data-section="location"]').hidden = false;
}
/* Coordinates */
if (geo.latitude || geo.longitude) {
document.querySelector('[data-value="coordinates"]').textContent =
geo.latitude.toFixed(4) + ', ' + geo.longitude.toFixed(4);
document.querySelector('[data-section="coordinates"]').hidden = false;
}
/* Details */
var detailParts = [];
if (geo.postal_code) detailParts.push(geo.postal_code);
if (geo.timezone) detailParts.push(geo.timezone);
if (geo.metro_code) detailParts.push('Metro ' + String(geo.metro_code));
if (geo.accuracy_radius) detailParts.push('±' + String(geo.accuracy_radius) + 'km');
if (detailParts.length) {
document.querySelector('[data-value="details"]').textContent = detailParts.join(' ');
document.querySelector('[data-section="details"]').hidden = false;
}
/* Traits */
var traitMap = {
anycast: 'anycast',
anonymous: 'anonymous_proxy',
satellite: 'satellite',
eu: 'country_in_eu'
};
var hasTraits = false;
var traitKeys = Object.keys(traitMap);
for (var i = 0; i < traitKeys.length; i++) {
if (geo[traitMap[traitKeys[i]]]) {
document.querySelector('[data-trait="' + traitKeys[i] + '"]').hidden = false;
hasTraits = true;
}
}
if (hasTraits) {
document.querySelector('[data-section="traits"]').hidden = false;
}
/* Registered country */
if (geo.registered_country) {
var rcParts = geo.registered_country +
(geo.registered_country_iso ? ' (' + geo.registered_country_iso + ')' : '');
document.querySelector('[data-value="registered-country"]').textContent = rcParts;
document.querySelector('[data-section="registered-country"]').hidden = false;
}
/* ASN */
if (geo.asn) {
document.querySelector('[data-value="asn"]').textContent =
'AS' + geo.asn + ' ' + (geo.asn_org || '');
} else {
document.querySelector('[data-value="asn"]').textContent = '—';
}
/* Blocklist */
var hasBlock = false;
if (data.blocked_inbound) {
document.querySelector('[data-block="inbound"]').hidden = false;
hasBlock = true;
}
if (data.blocked_outbound) {
document.querySelector('[data-block="outbound"]').hidden = false;
hasBlock = true;
}
if (!hasBlock) {
document.querySelector('[data-block="clean"]').hidden = false;
}
},
toggleIpInfo(event) {
event.preventDefault();
var link = document.querySelector('[data-my-ip-link]');
if (this.myIpMode) {
document.querySelector('[data-state="result"]').hidden = true;
link.textContent = 'Show my IP Info';
this.myIpMode = false;
} else {
link.textContent = 'Hide my IP Info';
this.check('');
}
},
init() {
var host = new URLSearchParams(window.location.search).get('host');
if (!host) {
var hashQuery = window.location.hash.split('?')[1];
if (hashQuery) {
host = new URLSearchParams(hashQuery).get('host');
}
}
if (host) {
document.querySelector('[data-input]').value = host;
this.check(host);
} else {
document.querySelector('[data-input]').focus();
}
}
};
App.init();