Archived
99 lines
3.4 KiB
JavaScript
99 lines
3.4 KiB
JavaScript
(() => {
|
|||
|
|
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);
|
||
|
|
});
|
||
|
|
})();
|