(data)
| 5050 | if (!target) { input.focus(); return; } |
| 5051 | const btn = event && event.target ? event.target : null; |
| 5052 | _ndBusy(btn, true, verb); |
| 5053 | out.classList.remove('hidden'); |
| 5054 | out.textContent = verb + ' ' + target + '…'; |
| 5055 | try { |
| 5056 | const data = await postAPI(endpoint, { target }); |
| 5057 | if (data.success) { |
| 5058 | out.textContent = data.output || '(no output)'; |
| 5059 | } else if (data.missing_tool && rerunFnName) { |
| 5060 | out.innerHTML = _ndMissingTool(data, rerunFnName); |
| 5061 | } else { |
| 5062 | out.textContent = 'Error: ' + (data.error || 'failed'); |
| 5063 | } |
| 5064 | } catch (e) { |
| 5065 | out.textContent = 'Failed: ' + e.message; |
| 5066 | } finally { |
| 5067 | _ndBusy(btn, false); |
| 5068 | } |
| 5069 | } |
| 5070 | |
| 5071 | function runPing() { return _ndRunText('ping-target', 'ping-results', '/api/net/ping', 'Pinging', 'runPing'); } |
| 5072 | function runTraceroute() { return _ndRunText('trace-target', 'trace-results', '/api/net/traceroute', 'Tracing', 'runTraceroute'); } |
| 5073 | function runWhois() { return _ndRunText('whois-target', 'whois-results', '/api/net/whois', 'Looking up', 'runWhois'); } |
| 5074 | |
| 5075 | // Fill the MTR start-point dropdown with this host's local IPv4 addresses. |
| 5076 | async function populateMtrSources() { |
| 5077 | const sel = document.getElementById('mtr-source'); |
| 5078 | if (!sel || sel.dataset._loaded) return; |
| 5079 | try { |
| 5080 | const data = await fetchAPI('/api/net/interfaces'); |
| 5081 | if (!data || !data.success) return; |
| 5082 | const seen = new Set(); |
| 5083 | (data.interfaces || []).forEach(i => { |
| 5084 | (i.ipv4 || []).forEach(cidr => { |
| 5085 | const ip = String(cidr).split('/')[0]; |
| 5086 | if (!ip || seen.has(ip)) return; |
| 5087 | seen.add(ip); |
| 5088 | const opt = document.createElement('option'); |
| 5089 | opt.value = ip; |
| 5090 | opt.textContent = i.name + ' — ' + ip; |
| 5091 | sel.appendChild(opt); |
| 5092 | }); |
| 5093 | }); |
| 5094 | sel.dataset._loaded = '1'; |
| 5095 | } catch (e) { /* leave just the auto option */ } |
| 5096 | } |
| 5097 | |
| 5098 | async function runMtr() { |
| 5099 | const target = (document.getElementById('mtr-target').value || '').trim(); |
| 5100 | const source = (document.getElementById('mtr-source').value || '').trim(); |
| 5101 | let count = parseInt(document.getElementById('mtr-count').value, 10); |
| 5102 | if (!Number.isFinite(count)) count = 5; |
| 5103 | count = Math.max(1, Math.min(20, count)); |
| 5104 | const out = document.getElementById('mtr-results'); |
| 5105 | if (!target) return; |
| 5106 | const btn = event && event.target ? event.target : null; |
| 5107 | _ndBusy(btn, true, 'Running…'); |
| 5108 | out.classList.remove('hidden'); |
| 5109 | out.innerHTML = '<p class="text-sm text-gray-400">Running MTR to ' + escapeHtml(target) |
no test coverage detected