From 8b10d85d296253375bf4ddad7c97350ca0883853 Mon Sep 17 00:00:00 2001 From: Rory& Date: Tue, 2 Dec 2025 16:46:08 +0100 Subject: [PATCH] Use IpDataClient in places --- src/api/routes/auth/location-metadata.ts | 5 +- src/api/routes/auth/register.ts | 6 +- src/api/util/handlers/Voice.ts | 10 +-- src/api/util/utility/ipAddress.ts | 76 ------------------- .../config/types/RegisterConfiguration.ts | 4 + 5 files changed, 15 insertions(+), 86 deletions(-) diff --git a/src/api/routes/auth/location-metadata.ts b/src/api/routes/auth/location-metadata.ts index 2ebfd0191..a08c98abe 100644 --- a/src/api/routes/auth/location-metadata.ts +++ b/src/api/routes/auth/location-metadata.ts @@ -16,7 +16,8 @@ along with this program. If not, see . */ -import { IPAnalysis, getIpAdress, route } from "@spacebar/api"; +import { getIpAdress, route } from "@spacebar/api"; +import { IpDataClient } from "@spacebar/util"; import { Request, Response, Router } from "express"; const router = Router({ mergeParams: true }); @@ -32,7 +33,7 @@ router.get( async (req: Request, res: Response) => { //TODO //Note: It's most likely related to legal. At the moment Discord hasn't finished this too - const country_code = (await IPAnalysis(getIpAdress(req))).country_code; + const country_code = (await IpDataClient.getIpInfo(getIpAdress(req)))?.country_code; res.json({ consent_required: false, country_code: country_code, diff --git a/src/api/routes/auth/register.ts b/src/api/routes/auth/register.ts index 2db60abd0..96e65b9a3 100644 --- a/src/api/routes/auth/register.ts +++ b/src/api/routes/auth/register.ts @@ -17,9 +17,7 @@ */ import { - IPAnalysis, getIpAdress, - isProxy, route, verifyCaptcha, } from "@spacebar/api"; @@ -30,6 +28,7 @@ import { User, ValidRegistrationToken, generateToken, + IpDataClient } from "@spacebar/util"; import bcrypt from "bcrypt"; import { Request, Response, Router } from "express"; @@ -148,7 +147,8 @@ router.post( } if (!regTokenUsed && register.blockProxies) { - if (isProxy(await IPAnalysis(ip))) { + const ipData = await IpDataClient.getIpInfo(ip); + if (ipData && IpDataClient.isProxy(ipData)) { console.log(`proxy ${ip} blocked from registration`); throw new HTTPError("Your IP is blocked from registration"); } diff --git a/src/api/util/handlers/Voice.ts b/src/api/util/handlers/Voice.ts index db06bd33c..21d5ee419 100644 --- a/src/api/util/handlers/Voice.ts +++ b/src/api/util/handlers/Voice.ts @@ -16,8 +16,8 @@ along with this program. If not, see . */ -import { Config } from "@spacebar/util"; -import { distanceBetweenLocations, IPAnalysis } from "../utility/ipAddress"; +import { Config, IpDataClient } from "@spacebar/util"; +import { distanceBetweenLocations } from "../utility/ipAddress"; export async function getVoiceRegions(ipAddress: string, vip: boolean) { const regions = Config.get().regions; @@ -27,15 +27,15 @@ export async function getVoiceRegions(ipAddress: string, vip: boolean) { let optimalId = regions.default; if (!regions.useDefaultAsOptimal) { - const clientIpAnalysis = await IPAnalysis(ipAddress); + const clientIpAnalysis = await IpDataClient.getIpInfo(ipAddress); let min = Number.POSITIVE_INFINITY; for (const ar of availableRegions) { //TODO the endpoint location should be saved in the database if not already present to prevent IPAnalysis call const dist = distanceBetweenLocations( - clientIpAnalysis, - ar.location || (await IPAnalysis(ar.endpoint)), + clientIpAnalysis!, + ar.location || (await IpDataClient.getIpInfo(ar.endpoint))!, ); if (dist < min) { diff --git a/src/api/util/utility/ipAddress.ts b/src/api/util/utility/ipAddress.ts index 2609dae12..e5acc89d9 100644 --- a/src/api/util/utility/ipAddress.ts +++ b/src/api/util/utility/ipAddress.ts @@ -18,82 +18,6 @@ import { Config } from "@spacebar/util"; import { Request } from "express"; -// use ipdata package instead of simple fetch because of integrated caching - -const exampleData = { - ip: "", - is_eu: true, - city: "", - region: "", - region_code: "", - country_name: "", - country_code: "", - continent_name: "", - continent_code: "", - latitude: 0, - longitude: 0, - postal: "", - calling_code: "", - flag: "", - emoji_flag: "", - emoji_unicode: "", - asn: { - asn: "", - name: "", - domain: "", - route: "", - type: "isp", - }, - languages: [ - { - name: "", - native: "", - }, - ], - currency: { - name: "", - code: "", - symbol: "", - native: "", - plural: "", - }, - time_zone: { - name: "", - abbr: "", - offset: "", - is_dst: true, - current_time: "", - }, - threat: { - is_tor: false, - is_proxy: false, - is_anonymous: false, - is_known_attacker: false, - is_known_abuser: false, - is_threat: false, - is_bogon: false, - }, - count: 0, - status: 200, -}; - -//TODO add function that support both ip and domain names -export async function IPAnalysis(ip: string): Promise { - const { ipdataApiKey } = Config.get().security; - if (!ipdataApiKey) return { ...exampleData, ip }; - - return ( - await fetch(`https://api.ipdata.co/${ip}?api-key=${ipdataApiKey}`) - ).json() as Promise; -} - -export function isProxy(data: typeof exampleData) { - if (!data || !data.asn || !data.threat) return false; - if (data.asn.type !== "isp") return true; - if (Object.values(data.threat).some((x) => x)) return true; - - return false; -} export function getIpAdress(req: Request): string { // TODO: express can do this (trustProxies: true)? diff --git a/src/util/config/types/RegisterConfiguration.ts b/src/util/config/types/RegisterConfiguration.ts index 9d8e036e1..c1e97593b 100644 --- a/src/util/config/types/RegisterConfiguration.ts +++ b/src/util/config/types/RegisterConfiguration.ts @@ -34,6 +34,10 @@ export class RegisterConfiguration { allowNewRegistration: boolean = true; allowMultipleAccounts: boolean = true; blockProxies: boolean = true; + blockIpDataCoThreatTypes: string[] = ["tor", "icloud_relay", "proxy", "datacenter", "anonymous", "known_attacker", "known_abuser", "threat"]; // matching ipdata's threat.is_* fields as of 2025/11/30, minus bogon + blockAsnTypes: string[] = [""]; + blockAsns: string[] = [""]; + blockAbuseIpDbAboveScore: number = 0; // 0 to disable incrementingDiscriminators: boolean = false; // random otherwise defaultRights: string = "875069521787904"; // See `npm run generate:rights` }