Archived
Update visible examples with visitor IP
This commit is contained in:
1 parent
8de260dfc7
commit
03ef2d9af6
6 files changed
+67
-2
No files matched your search
@@ -137,6 +137,7 @@ def _page(
|
||||
{preload_logo_html}
|
||||
<script src="/theme.js?v=2"></script>
|
||||
<script src="/clipboard.js?v=3" defer></script>
|
||||
<script src="/visitor-ip.js?v=1" defer></script>
|
||||
{extra_scripts_html}
|
||||
<link href="/bootstrap-subset.css?v=3" rel="stylesheet">
|
||||
<link href="/app.css?v=13" rel="stylesheet">
|
||||
|
||||
@@ -190,3 +190,55 @@ document.querySelectorAll("[data-admin-table]").forEach((tableShell) => {
|
||||
render();
|
||||
});
|
||||
""".strip()
|
||||
|
||||
|
||||
VISITOR_IP_JS = """
|
||||
(() => {
|
||||
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);
|
||||
};
|
||||
|
||||
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)));
|
||||
await Promise.allSettled(tasks);
|
||||
});
|
||||
})();
|
||||
""".strip()
|
||||
@@ -132,7 +132,7 @@ def content_security_policy(path: str) -> str:
|
||||
"style-src 'self'; "
|
||||
"img-src 'self' data:; "
|
||||
"font-src 'self'; "
|
||||
"connect-src 'self'; "
|
||||
"connect-src 'self' https://api4.ipify.org https://api6.ipify.org; "
|
||||
"form-action 'self'; "
|
||||
"frame-ancestors 'none'"
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user