mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
67 lines
2.0 KiB
JavaScript
67 lines
2.0 KiB
JavaScript
'use strict';
|
|
|
|
const axios = require('axios');
|
|
const UAParser = require('ua-parser-js');
|
|
|
|
const LOCALHOST = new Set(['::1', '127.0.0.1', '::ffff:127.0.0.1']);
|
|
|
|
const getIP = (req) => {
|
|
const forwarded = req.headers['x-forwarded-for'];
|
|
if (forwarded) return forwarded.split(',')[0].trim();
|
|
return req.ip || req.connection?.remoteAddress || null;
|
|
};
|
|
|
|
const parseUA = (uaString) => {
|
|
const p = new UAParser(uaString || '');
|
|
return {
|
|
ua: uaString || 'unknown',
|
|
browser: [p.getBrowser().name, p.getBrowser().version].filter(Boolean).join(' ') || 'unknown',
|
|
os: [p.getOS().name, p.getOS().version].filter(Boolean).join(' ') || 'unknown',
|
|
device: p.getDevice().type || 'desktop',
|
|
};
|
|
};
|
|
|
|
const getGeo = async (ip) => {
|
|
if (!ip || LOCALHOST.has(ip)) return { country: null, region: null, city: null, lat: null, lon: null };
|
|
|
|
try {
|
|
const { data } = await axios.get(
|
|
`http://ip-api.com/json/${ip}?fields=status,country,regionName,city,lat,lon`,
|
|
{ timeout: 3000 }
|
|
);
|
|
if (data.status !== 'success') return { country: null, region: null, city: null, lat: null, lon: null };
|
|
return { country: data.country, region: data.regionName, city: data.city, lat: data.lat, lon: data.lon };
|
|
} catch {
|
|
return { country: null, region: null, city: null, lat: null, lon: null };
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Builds a rich session info object from the request.
|
|
* Used for both login_info and logout_info.
|
|
*
|
|
* @param {import('express').Request} req
|
|
* @param {Object} extras — e.g. { forced_by: admin_user_id }
|
|
* @returns {Promise<Object>}
|
|
*/
|
|
const buildSessionInfo = async (req, extras = {}) => {
|
|
const ip = getIP(req);
|
|
const geo = await getGeo(ip);
|
|
|
|
return {
|
|
date: new Date().toISOString(),
|
|
ip_address: ip,
|
|
country: geo.country,
|
|
region: geo.region,
|
|
city: geo.city,
|
|
lat: geo.lat,
|
|
lon: geo.lon,
|
|
device_info: parseUA(req.headers['user-agent']),
|
|
...extras,
|
|
};
|
|
};
|
|
|
|
module.exports = buildSessionInfo;
|
|
module.exports.parseUA = parseUA;
|
|
module.exports.getIP = getIP;
|