|
const { Server } = require("socket.io"); |
|
|
|
|
|
const port = 7860; |
|
const io = new Server(port, { |
|
cors: { |
|
origin: "*", |
|
} |
|
}); |
|
|
|
let activeUsers = 0; |
|
const userSessions = {}; |
|
const userSessionHistory = []; |
|
|
|
|
|
function isPrivateIP(ip) { |
|
const parts = ip.split('.').map(part => parseInt(part, 10)); |
|
if (parts.length !== 4) return false; |
|
const [a, b] = parts; |
|
|
|
return ( |
|
a === 10 || |
|
(a === 172 && b >= 16 && b <= 31) || |
|
(a === 192 && b === 168) || |
|
a === 127 || |
|
a === 0 |
|
); |
|
} |
|
|
|
async function fetchIpInfo(ip) { |
|
try { |
|
const controller = new AbortController(); |
|
const timeout = setTimeout(() => controller.abort(), 5000); |
|
|
|
const res = await fetch(`https://ipinfo.io/${ip}/json`, { |
|
signal: controller.signal, |
|
}); |
|
|
|
clearTimeout(timeout); |
|
|
|
if (!res.ok) throw new Error(`HTTP error ${res.status}`); |
|
return await res.json(); |
|
} catch (e) { |
|
if (e.name === 'AbortError') { |
|
console.error("IP info fetch timed out for IP:", ip); |
|
} else { |
|
console.error("IP info fetch failed:", e); |
|
} |
|
return null; |
|
} |
|
} |
|
|
|
io.on("connection", async (socket) => { |
|
if (socket.handshake.query.isAdmin === "true") { |
|
|
|
socket.emit("userSessionHistory", userSessionHistory); |
|
|
|
|
|
socket.emit("updateUserCount", activeUsers); |
|
socket.emit("userSessionsUpdate", userSessions); |
|
|
|
return; |
|
} |
|
|
|
console.log(`New connection from ${socket.id}, isAdmin: ${socket.handshake.query.isAdmin}`); |
|
|
|
activeUsers++; |
|
|
|
|
|
let ips = socket.handshake.headers['x-forwarded-for'] || socket.handshake.address; |
|
if (typeof ips === 'string') { |
|
ips = ips.split(',').map(ip => ip.trim()); |
|
} else { |
|
ips = [ips]; |
|
} |
|
|
|
const ipString = ips.join(', '); |
|
const connectTime = new Date(); |
|
|
|
userSessions[socket.id] = { |
|
socketId: socket.id, |
|
ip: ipString, |
|
connectTime, |
|
disconnectTime: null, |
|
loc: null, |
|
city: null, |
|
region: null, |
|
country: null, |
|
}; |
|
|
|
|
|
const firstPublicIp = ips.find(ip => ip && !isPrivateIP(ip)); |
|
if (firstPublicIp) { |
|
const ipInfo = await fetchIpInfo(firstPublicIp); |
|
if (ipInfo) { |
|
userSessions[socket.id].loc = ipInfo.loc || null; |
|
userSessions[socket.id].city = ipInfo.city || null; |
|
userSessions[socket.id].region = ipInfo.region || null; |
|
userSessions[socket.id].country = ipInfo.country || null; |
|
} |
|
} |
|
|
|
io.emit("updateUserCount", activeUsers); |
|
io.emit("userSessionsUpdate", userSessions); |
|
|
|
socket.on("disconnect", () => { |
|
activeUsers--; |
|
const disconnectTime = new Date(); |
|
|
|
if (userSessions[socket.id]) { |
|
userSessions[socket.id].disconnectTime = disconnectTime; |
|
|
|
|
|
userSessionHistory.push({ ...userSessions[socket.id] }); |
|
|
|
|
|
} |
|
|
|
io.emit("updateUserCount", activeUsers); |
|
io.emit("userSessionsUpdate", userSessions); |
|
}); |
|
}); |