// --------------------------------------------------------- // Tool tab navigation // --------------------------------------------------------- const toolTabs = document.querySelectorAll(".tool-tab"); const toolPanels = document.querySelectorAll(".tool-panel"); toolTabs.forEach((tab) => { tab.addEventListener("click", () => { const selectedToolId = tab.dataset.tool; // Update the active tab. toolTabs.forEach((currentTab) => { currentTab.classList.toggle("active", currentTab === tab); }); // Show only the selected tool panel. toolPanels.forEach((panel) => { panel.hidden = panel.id !== selectedToolId; }); }); }); // --------------------------------------------------------- // Website Status Checker // --------------------------------------------------------- const uptimeForm = document.getElementById("uptime-form"); const urlInput = document.getElementById("url-input"); const checkButton = document.getElementById("check-button"); const statusMessage = document.getElementById("status-message"); const resultPanel = document.getElementById("result-panel"); const onlineBadge = document.getElementById("online-badge"); const statusCode = document.getElementById("status-code"); const responseTime = document.getElementById("response-time"); const redirectCount = document.getElementById("redirect-count"); const checkedAt = document.getElementById("checked-at"); const finalUrl = document.getElementById("final-url"); uptimeForm.addEventListener("submit", async (event) => { event.preventDefault(); const url = urlInput.value.trim(); statusMessage.textContent = "Checking website..."; statusMessage.className = "status-message"; resultPanel.hidden = true; checkButton.disabled = true; checkButton.textContent = "Checking..."; try { const response = await fetch("/api/uptime", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ url }), }); const result = await response.json(); if (!response.ok) { throw new Error(result.error || "The request failed."); } if (!result.online) { throw new Error(result.error || "The website could not be reached."); } onlineBadge.textContent = "Online"; onlineBadge.className = "status-badge online"; statusCode.textContent = result.statusCode; responseTime.textContent = `${result.responseTimeMs} ms`; redirectCount.textContent = result.redirectCount; checkedAt.textContent = new Date(result.checkedAt).toLocaleString(); finalUrl.textContent = result.finalUrl; finalUrl.href = result.finalUrl; statusMessage.textContent = "Website check completed."; resultPanel.hidden = false; } catch (error) { statusMessage.textContent = error.message; statusMessage.className = "status-message error"; } finally { checkButton.disabled = false; checkButton.textContent = "Check Website"; } }); // --------------------------------------------------------- // DNS Lookup // --------------------------------------------------------- const dnsForm = document.getElementById("dns-form"); const hostnameInput = document.getElementById("hostname-input"); const dnsButton = document.getElementById("dns-button"); const dnsMessage = document.getElementById("dns-message"); const dnsResultPanel = document.getElementById("dns-result-panel"); const dnsHostname = document.getElementById("dns-hostname"); const dnsRecords = document.getElementById("dns-records"); const dnsCheckedAt = document.getElementById("dns-checked-at"); // Convert one DNS record into readable text. function formatDnsRecord(recordType, record) { if (recordType === "MX" && typeof record === "object") { return `${record.exchange} (priority ${record.priority})`; } return String(record); } // Build one visible record group. function createDnsRecordGroup(recordType, records) { const group = document.createElement("section"); group.className = "dns-record-group"; const heading = document.createElement("h4"); heading.textContent = recordType; group.appendChild(heading); if (!Array.isArray(records) || records.length === 0) { const emptyMessage = document.createElement("p"); emptyMessage.className = "empty-record"; emptyMessage.textContent = "No records found."; group.appendChild(emptyMessage); return group; } const list = document.createElement("ul"); list.className = "dns-record-list"; records.forEach((record) => { const item = document.createElement("li"); item.textContent = formatDnsRecord(recordType, record); list.appendChild(item); }); group.appendChild(list); return group; } dnsForm.addEventListener("submit", async (event) => { event.preventDefault(); const hostname = hostnameInput.value.trim(); dnsMessage.textContent = "Looking up DNS records..."; dnsMessage.className = "status-message"; dnsResultPanel.hidden = true; dnsButton.disabled = true; dnsButton.textContent = "Looking Up..."; try { const response = await fetch("/api/dns", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ hostname }), }); const result = await response.json(); if (!response.ok) { throw new Error(result.error || "The DNS lookup failed."); } dnsHostname.textContent = result.hostname; dnsRecords.replaceChildren(); const recordOrder = ["A", "AAAA", "CNAME", "MX", "TXT", "NS"]; recordOrder.forEach((recordType) => { const group = createDnsRecordGroup( recordType, result.records[recordType] ); dnsRecords.appendChild(group); }); dnsCheckedAt.textContent = `Checked ${new Date(result.checkedAt).toLocaleString()}`; dnsMessage.textContent = "DNS lookup completed."; dnsResultPanel.hidden = false; } catch (error) { dnsMessage.textContent = error.message; dnsMessage.className = "status-message error"; } finally { dnsButton.disabled = false; dnsButton.textContent = "Look Up DNS"; } }); // --------------------------------------------------------- // SSL Certificate Checker // --------------------------------------------------------- // Get references to the SSL form and result elements. const sslForm = document.getElementById("ssl-form"); const sslHostnameInput = document.getElementById( "ssl-hostname-input" ); const sslButton = document.getElementById("ssl-button"); const sslMessage = document.getElementById("ssl-message"); const sslResultPanel = document.getElementById( "ssl-result-panel" ); const sslStatusBadge = document.getElementById( "ssl-status-badge" ); const sslHostname = document.getElementById("ssl-hostname"); const sslDaysRemaining = document.getElementById( "ssl-days-remaining" ); const sslValidFrom = document.getElementById("ssl-valid-from"); const sslValidTo = document.getElementById("ssl-valid-to"); const sslProtocol = document.getElementById("ssl-protocol"); const sslCipher = document.getElementById("ssl-cipher"); const sslAddress = document.getElementById("ssl-address"); const sslCheckedAt = document.getElementById("ssl-checked-at"); const sslSubject = document.getElementById("ssl-subject"); const sslIssuer = document.getElementById("ssl-issuer"); const sslFingerprint = document.getElementById( "ssl-fingerprint" ); const sslAuthorizationErrorBlock = document.getElementById( "ssl-authorization-error-block" ); const sslAuthorizationError = document.getElementById( "ssl-authorization-error" ); // Convert certificate date strings into a readable local date. function formatCertificateDate(value) { if (!value) { return "Unknown"; } const date = new Date(value); if (Number.isNaN(date.getTime())) { return value; } return date.toLocaleString(); } // Choose readable text for the certificate expiration state. function getExpirationText(daysRemaining) { if (daysRemaining === null || daysRemaining === undefined) { return "Unknown"; } if (daysRemaining < 0) { return `${Math.abs(daysRemaining)} days expired`; } if (daysRemaining === 0) { return "Expires today"; } return `${daysRemaining} days`; } // Handle SSL certificate form submissions. sslForm.addEventListener("submit", async (event) => { event.preventDefault(); const hostname = sslHostnameInput.value.trim(); // Reset the SSL interface before beginning the request. sslMessage.textContent = "Checking certificate..."; sslMessage.className = "status-message"; sslResultPanel.hidden = true; sslButton.disabled = true; sslButton.textContent = "Checking..."; try { const response = await fetch("/api/ssl", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ hostname }), }); const result = await response.json(); if (!response.ok) { throw new Error( result.error || "The SSL certificate check failed." ); } // Show whether Node trusted the certificate chain and hostname. if (result.authorized) { sslStatusBadge.textContent = "Valid"; sslStatusBadge.className = "status-badge online"; } else { sslStatusBadge.textContent = "Not trusted"; sslStatusBadge.className = "status-badge offline"; } // Populate the certificate summary. sslHostname.textContent = result.hostname; sslDaysRemaining.textContent = getExpirationText( result.daysRemaining ); sslValidFrom.textContent = formatCertificateDate( result.validFrom ); sslValidTo.textContent = formatCertificateDate( result.validTo ); sslProtocol.textContent = result.protocol || "Unknown"; sslCipher.textContent = result.cipher || "Unknown"; sslAddress.textContent = result.resolvedAddress ? `${result.resolvedAddress} (IPv${result.addressFamily})` : "Unknown"; sslCheckedAt.textContent = formatCertificateDate( result.checkedAt ); // Populate the longer certificate values. sslSubject.textContent = result.subject || "Unknown"; sslIssuer.textContent = result.issuer || "Unknown"; sslFingerprint.textContent = result.fingerprint256 || "Unavailable"; // Show the authorization problem only when one exists. if (result.authorizationError) { sslAuthorizationError.textContent = result.authorizationError; sslAuthorizationErrorBlock.hidden = false; } else { sslAuthorizationError.textContent = ""; sslAuthorizationErrorBlock.hidden = true; } sslMessage.textContent = "Certificate check completed."; sslResultPanel.hidden = false; } catch (error) { sslMessage.textContent = error.message; sslMessage.className = "status-message error"; } finally { sslButton.disabled = false; sslButton.textContent = "Check Certificate"; } });