首选库内匹配
This commit is contained in:
@@ -33,38 +33,49 @@ async function getLocation(target) {
|
|||||||
// Normalize target (strip port if present)
|
// Normalize target (strip port if present)
|
||||||
const cleanTarget = target.split(':')[0];
|
const cleanTarget = target.split(':')[0];
|
||||||
|
|
||||||
// Resolve domain to IP if needed
|
// 1. Check if we already have this IP/Domain in DB (FASTEST)
|
||||||
let cleanIp = cleanTarget;
|
|
||||||
if (net.isIP(cleanTarget) === 0) {
|
|
||||||
try {
|
|
||||||
console.log(`[Geo Service] Resolving domain to IP: ${cleanTarget}`);
|
|
||||||
const lookup = await dns.lookup(cleanTarget);
|
|
||||||
cleanIp = lookup.address;
|
|
||||||
} catch (err) {
|
|
||||||
console.error(`[Geo Service] DNS resolution failed for ${cleanTarget}:`, err.message);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip local/reserved IPs
|
|
||||||
if (isLocalIp(cleanIp)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check database first
|
|
||||||
try {
|
try {
|
||||||
const [rows] = await db.query('SELECT * FROM server_locations WHERE ip = ?', [cleanIp]);
|
const [rows] = await db.query('SELECT * FROM server_locations WHERE ip = ?', [cleanTarget]);
|
||||||
if (rows.length > 0) {
|
if (rows.length > 0) {
|
||||||
// Check if data is stale (e.g., older than 30 days)
|
|
||||||
const data = rows[0];
|
const data = rows[0];
|
||||||
const age = Date.now() - new Date(data.last_updated).getTime();
|
const age = Date.now() - new Date(data.last_updated).getTime();
|
||||||
if (age < 30 * 24 * 60 * 60 * 1000) {
|
if (age < 30 * 24 * 60 * 60 * 1000) {
|
||||||
return normalizeGeo(data);
|
return normalizeGeo(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// console.error(`[Geo Service] DB check failed for ${cleanTarget}`);
|
||||||
|
}
|
||||||
|
|
||||||
// Resolve via ipinfo.io
|
// 2. Resolve domain to IP if needed
|
||||||
console.log(`[Geo Service] Resolving location for IP: ${cleanIp}`);
|
let cleanIp = cleanTarget;
|
||||||
|
if (net.isIP(cleanTarget) === 0) {
|
||||||
|
try {
|
||||||
|
const lookup = await dns.lookup(cleanTarget);
|
||||||
|
cleanIp = lookup.address;
|
||||||
|
|
||||||
|
// Secondary DB check with resolved IP
|
||||||
|
const [rows] = await db.query('SELECT * FROM server_locations WHERE ip = ?', [cleanIp]);
|
||||||
|
if (rows.length > 0) {
|
||||||
|
return normalizeGeo(rows[0]);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// Quiet DNS failure for tokens (legacy bug mitigation)
|
||||||
|
if (!/^[0-9a-f]{16}$/i.test(cleanTarget)) {
|
||||||
|
console.error(`[Geo Service] DNS resolution failed for ${cleanTarget}:`, err.message);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Skip local/reserved IPs
|
||||||
|
if (isLocalIp(cleanIp)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Resolve via ipinfo.io (LAST RESORT)
|
||||||
|
try {
|
||||||
|
console.log(`[Geo Service] API lookup (ipinfo.io) for: ${cleanIp}`);
|
||||||
const url = `https://ipinfo.io/${cleanIp}/json${ipInfoToken ? `?token=${ipInfoToken}` : ''}`;
|
const url = `https://ipinfo.io/${cleanIp}/json${ipInfoToken ? `?token=${ipInfoToken}` : ''}`;
|
||||||
const response = await axios.get(url, { timeout: 5000 });
|
const response = await axios.get(url, { timeout: 5000 });
|
||||||
const geo = normalizeGeo(response.data);
|
const geo = normalizeGeo(response.data);
|
||||||
|
|||||||
Reference in New Issue
Block a user