type UnknownMap = Record; export const MAP_LOCATION_CLASSIFICATIONS = ["clear", "hosting"] as const; function objectValue(value: unknown): UnknownMap | null { return value && typeof value === "object" && !Array.isArray(value) ? value as UnknownMap : null; } function stringValue(value: unknown) { return typeof value === "string" && value.trim() ? value.trim() : null; } function proxyValue(value: unknown) { if (typeof value === "boolean") return value; if (typeof value === "string" && value.toLowerCase() === "yes") return true; if (typeof value === "string" && value.toLowerCase() === "no") return false; return null; } function coordinate(value: unknown) { if (typeof value === "number" && Number.isFinite(value)) return value; if (typeof value === "string" && value.trim() && Number.isFinite(Number(value))) return Number(value); return null; } export interface ParsedUserLocation { latitude: number; longitude: number; label: string; } export interface ParsedUserNetwork { asn: string | null; provider: string | null; connectionType: string | null; proxy: boolean | null; } export function parseUserNetwork(value: unknown): ParsedUserNetwork { const intelligence = objectValue(value); const network = objectValue(intelligence?.network); const providerResponse = objectValue(intelligence?.rawResponse); const legacyDetails = Object.values(providerResponse ?? {}) .map(objectValue) .find((details) => details && ("type" in details || "proxy" in details)); return { asn: stringValue(network?.asn), provider: stringValue(network?.provider), connectionType: stringValue(network?.connectionType) ?? stringValue(legacyDetails?.type), proxy: proxyValue(network?.proxy) ?? proxyValue(legacyDetails?.proxy), }; } export function parseUserLocation(value: unknown): ParsedUserLocation | null { const intelligence = objectValue(value); const location = objectValue(intelligence?.location); if (!location) return null; const latitude = coordinate(location.latitude); const longitude = coordinate(location.longitude); if (latitude === null || longitude === null || latitude < -90 || latitude > 90 || longitude < -180 || longitude > 180) { return null; } const label = [location.city, location.region, location.countryCode ?? location.country] .filter((part): part is string => typeof part === "string" && part.trim().length > 0) .join(", "); return { latitude, longitude, label: label || "Approximate location unavailable" }; } export function groupMapLocations(locations: T[]) { const grouped = new Map(); for (const location of locations) { const roundedLatitude = Number(location.latitude.toFixed(2)); const latitude = roundedLatitude === 0 ? 0 : roundedLatitude; const roundedLongitude = Number(location.longitude.toFixed(2)); const longitude = Math.abs(roundedLongitude) === 180 ? -180 : roundedLongitude; const key = `${latitude}:${longitude}`; const group = grouped.get(key); if (group) group.locations.push(location); else grouped.set(key, { latitude, longitude, locations: [location] }); } return [...grouped.entries()].map(([key, group]) => ({ key, latitude: group.latitude, longitude: group.longitude, count: group.locations.length, nicknames: [...group.locations.map((location) => location.nickname)].sort((left, right) => left.localeCompare(right)), locations: group.locations, })); } export function projectWorldPoint(latitude: number, longitude: number, width: number, height: number) { return { x: ((longitude + 180) / 360) * width, y: ((90 - latitude) / 180) * height, }; }