diff --git a/src/index.mjs b/src/index.mjs
index f412f42..70cbadc 100644
--- a/src/index.mjs
+++ b/src/index.mjs
@@ -246,9 +246,21 @@ try {
}
// Called on every gated request — produces a fresh page with unique Ray ID + timestamp
-function buildGatePage() {
+// Accepts an optional request object to inject the visitor's real IP into the footer reveal.
+function buildGatePage(req) {
if (!_cfRender) return nginx502Fallback;
+
let html = _cfRender({ ...gateOptions, what_can_i_do: gateSignInButton });
+
+ // Inject real visitor IP into the footer "Your IP: [Click to reveal]" span
+ if (req) {
+ const visitorIp = security.getRealIP(req);
+ html = html.replace(
+ '',
+ ``
+ );
+ }
+
// Make the second 'a' in "Bad Gateway" a secret click trigger
html = html.replace(
'Bad Gateway',
@@ -468,7 +480,7 @@ process.on('uncaughtException', err => {
return;
if (req.url.pathname.match(/^\/(b|t|ca|a|memes)\//) || req.url.pathname.startsWith('/s/emojis/')) {
if (cfg.websrv.private_society && !req.cookies?.session) {
- res.writeHead(200, { 'Content-Type': 'text/html' }).end(nginx502 ?? buildGatePage());
+ res.writeHead(200, { 'Content-Type': 'text/html' }).end(nginx502 ?? buildGatePage(req));
req.url.pathname = '/private_society_media_bypass';
return;
}
@@ -658,13 +670,13 @@ process.on('uncaughtException', err => {
}
// For page requests, return 502 Bad Gateway for all paths except homepage (which shows the gate)
if (req.url.pathname !== '/') {
- res.writeHead(200, { 'Content-Type': 'text/html' }).end(nginx502 ?? buildGatePage());
+ res.writeHead(200, { 'Content-Type': 'text/html' }).end(nginx502 ?? buildGatePage(req));
req.url.pathname = '/private_society_bypass';
return;
}
// Homepage: in cloudflare dynamic mode serve gate directly; otherwise fall through to template
if (nginx502 === null) {
- res.writeHead(200, { 'Content-Type': 'text/html' }).end(buildGatePage());
+ res.writeHead(200, { 'Content-Type': 'text/html' }).end(buildGatePage(req));
req.url.pathname = '/private_society_bypass';
return;
}