(() => { const ipv4Placeholder = "203.0.113.10"; const ipv6Placeholder = "2001:db8::10"; const needsIpv4 = () => ( document.body.textContent.includes(ipv4Placeholder) || document.querySelector(`[data-copy*="${ipv4Placeholder}"]`) ); const needsIpv6 = () => ( document.body.textContent.includes(ipv6Placeholder) || document.querySelector(`[data-copy*="${ipv6Placeholder}"]`) ); const fetchIp = async (url) => { try { const response = await fetch(url, { cache: "no-store", mode: "cors" }); if (!response.ok) return ""; const payload = await response.json(); return typeof payload.ip === "string" ? payload.ip : ""; } catch (_) { return ""; } }; const replaceInTextNodes = (search, replacement) => { const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT); const nodes = []; while (walker.nextNode()) { if (walker.currentNode.nodeValue.includes(search)) nodes.push(walker.currentNode); } nodes.forEach((node) => { node.nodeValue = node.nodeValue.split(search).join(replacement); }); }; const replaceInCopyValues = (search, replacement) => { document.querySelectorAll("[data-copy]").forEach((element) => { const value = element.dataset.copy || ""; if (value.includes(search)) element.dataset.copy = value.split(search).join(replacement); }); }; const replaceEverywhere = (search, replacement) => { if (!replacement || replacement === search) return; replaceInTextNodes(search, replacement); replaceInCopyValues(search, replacement); }; const updateCopyCommand = (button, ipv6Command) => { const value = button.dataset.copy || ""; if (!value || value.includes("?myipv6=")) return; const lines = value.split("\n"); const output = []; let inserted = false; lines.forEach((line) => { output.push(line); if (!inserted && line.includes("/api/v1/router/update/") && line.includes("?myip=")) { output.push(ipv6Command); inserted = true; } }); if (inserted) button.dataset.copy = output.join("\n"); }; const insertIpv6Examples = (ip) => { if (!ip) return; document.querySelectorAll(".terminal-card.manual-code").forEach((card) => { if (card.textContent.includes("?myipv6=")) return; const lines = [...card.querySelectorAll("code")]; const ipv4Line = lines.find((line) => ( line.textContent.includes("/api/v1/router/update/") && line.textContent.includes("?myip=") )); if (!ipv4Line) return; const base = ipv4Line.textContent.split("?myip=", 1)[0].replace(/'$/, ""); const ipv6Command = `${base}?myipv6=${ip}'`; const code = document.createElement("code"); code.textContent = ipv6Command; ipv4Line.after(code); const copyButton = card.querySelector("[data-copy]"); if (copyButton) updateCopyCommand(copyButton, ipv6Command); }); }; document.addEventListener("DOMContentLoaded", async () => { const tasks = []; if (needsIpv4()) { tasks.push(fetchIp("https://api4.ipify.org?format=json").then((ip) => { replaceEverywhere(ipv4Placeholder, ip); })); } if (needsIpv6()) { tasks.push(fetchIp("https://api6.ipify.org?format=json").then((ip) => { replaceEverywhere(ipv6Placeholder, ip); insertIpv6Examples(ip); })); } await Promise.allSettled(tasks); }); })();