mirror of
https://github.com/jakejarvis/hoot.git
synced 2025-10-18 20:14:25 -04:00
Update hosting schema to include country_code and remove emoji field
This commit is contained in:
@@ -85,9 +85,9 @@ describe("DomainReportView", () => {
|
||||
city: "",
|
||||
region: "",
|
||||
country: "",
|
||||
country_code: "",
|
||||
lat: null,
|
||||
lon: null,
|
||||
emoji: null,
|
||||
},
|
||||
},
|
||||
isError: false,
|
||||
|
@@ -26,9 +26,9 @@ describe("HostingEmailSection", () => {
|
||||
city: "",
|
||||
region: "",
|
||||
country: "",
|
||||
country_code: "",
|
||||
lat: null,
|
||||
lon: null,
|
||||
emoji: null,
|
||||
},
|
||||
} as unknown as import("@/lib/schemas").Hosting;
|
||||
render(
|
||||
|
@@ -9,9 +9,9 @@ export const HostingSchema = z.object({
|
||||
city: z.string(),
|
||||
region: z.string(),
|
||||
country: z.string(),
|
||||
country_code: z.string(),
|
||||
lat: z.number().nullable(),
|
||||
lon: z.number().nullable(),
|
||||
emoji: z.string().nullable(),
|
||||
}),
|
||||
});
|
||||
|
||||
|
@@ -23,9 +23,9 @@ vi.mock("@/server/services/ip", () => ({
|
||||
city: "",
|
||||
region: "",
|
||||
country: "",
|
||||
country_code: "",
|
||||
lat: null,
|
||||
lon: null,
|
||||
emoji: null,
|
||||
},
|
||||
owner: null,
|
||||
domain: null,
|
||||
@@ -69,12 +69,11 @@ describe("detectHosting", () => {
|
||||
]);
|
||||
(lookupIpMeta as unknown as Mock).mockResolvedValue({
|
||||
geo: {
|
||||
city: "SF",
|
||||
city: "San Francisco",
|
||||
region: "CA",
|
||||
country: "US",
|
||||
lat: 1,
|
||||
lon: 2,
|
||||
emoji: "🇺🇸",
|
||||
},
|
||||
owner: null,
|
||||
domain: null,
|
||||
@@ -134,9 +133,9 @@ describe("detectHosting", () => {
|
||||
city: "",
|
||||
region: "",
|
||||
country: "",
|
||||
country_code: "",
|
||||
lat: null,
|
||||
lon: null,
|
||||
emoji: null,
|
||||
},
|
||||
owner: "My ISP",
|
||||
domain: "isp.example",
|
||||
|
@@ -39,9 +39,9 @@ export async function detectHosting(domain: string): Promise<Hosting> {
|
||||
city: "",
|
||||
region: "",
|
||||
country: "",
|
||||
country_code: "",
|
||||
lat: null,
|
||||
lon: null,
|
||||
emoji: null,
|
||||
},
|
||||
owner: null,
|
||||
domain: null,
|
||||
|
@@ -9,12 +9,12 @@ afterEach(() => {
|
||||
describe("lookupIpMeta", () => {
|
||||
it("parses ipwho.is response and derives owner and domain", async () => {
|
||||
const resp = {
|
||||
city: "SF",
|
||||
city: "San Francisco",
|
||||
region: "CA",
|
||||
country: "US",
|
||||
country: "United States",
|
||||
country_code: "US",
|
||||
latitude: 37.7,
|
||||
longitude: -122.4,
|
||||
flag: { emoji: "🇺🇸" },
|
||||
connection: {
|
||||
org: "Cloudflare",
|
||||
isp: "Cloudflare, Inc",
|
||||
@@ -25,7 +25,7 @@ describe("lookupIpMeta", () => {
|
||||
.spyOn(global, "fetch")
|
||||
.mockResolvedValue(new Response(JSON.stringify(resp), { status: 200 }));
|
||||
const res = await lookupIpMeta("1.2.3.4");
|
||||
expect(res.geo.city).toBe("SF");
|
||||
expect(res.geo.city).toBe("San Francisco");
|
||||
expect(res.owner).toBe("Cloudflare");
|
||||
expect(res.domain).toBe("cloudflare.com");
|
||||
fetchMock.mockRestore();
|
||||
|
@@ -3,9 +3,9 @@ export async function lookupIpMeta(ip: string): Promise<{
|
||||
city: string;
|
||||
region: string;
|
||||
country: string;
|
||||
country_code: string;
|
||||
lat: number | null;
|
||||
lon: number | null;
|
||||
emoji: string | null;
|
||||
};
|
||||
owner: string | null;
|
||||
domain: string | null;
|
||||
@@ -17,52 +17,80 @@ export async function lookupIpMeta(ip: string): Promise<{
|
||||
if (!res.ok) throw new Error("ipwho.is fail");
|
||||
|
||||
const j = (await res.json()) as {
|
||||
city?: string;
|
||||
region?: string;
|
||||
state?: string;
|
||||
ip?: string;
|
||||
success?: boolean;
|
||||
type?: "IPv4" | "IPv6";
|
||||
continent?: string;
|
||||
continent_code?: string;
|
||||
country?: string;
|
||||
country_code?: string;
|
||||
region?: string;
|
||||
region_code?: string;
|
||||
city?: string;
|
||||
latitude?: number;
|
||||
longitude?: number;
|
||||
flag?: { emoji?: string };
|
||||
connection?: { org?: string; isp?: string; domain?: string };
|
||||
is_eu?: boolean;
|
||||
postal?: string;
|
||||
calling_code?: string;
|
||||
capital?: string;
|
||||
borders?: string; // e.g., "CA,MX"
|
||||
flag?: {
|
||||
img?: string; // URL to SVG/PNG
|
||||
emoji?: string; // e.g., "🇺🇸"
|
||||
emoji_unicode?: string; // e.g., "U+1F1FA U+1F1F8"
|
||||
};
|
||||
connection: {
|
||||
asn?: number;
|
||||
org?: string;
|
||||
isp?: string;
|
||||
domain?: string;
|
||||
};
|
||||
timezone?: {
|
||||
id?: string; // IANA TZ, e.g., "America/New_York"
|
||||
abbr?: string; // e.g., "EDT"
|
||||
is_dst?: boolean;
|
||||
offset?: number; // seconds offset from UTC (can be negative)
|
||||
utc?: string; // e.g., "-04:00"
|
||||
current_time?: string; // ISO8601 with offset
|
||||
};
|
||||
};
|
||||
|
||||
console.debug("[ip] ipwho.is result", { ip, json: j });
|
||||
|
||||
const geo = {
|
||||
city: j.city || "",
|
||||
region: j.region || j.state || "",
|
||||
country: j.country || "",
|
||||
lat: typeof j.latitude === "number" ? j.latitude : null,
|
||||
lon: typeof j.longitude === "number" ? j.longitude : null,
|
||||
emoji: j.flag?.emoji || null,
|
||||
};
|
||||
const org = j.connection?.org?.trim();
|
||||
const isp = j.connection?.isp?.trim();
|
||||
const owner = (org || isp || "").trim() || null;
|
||||
const domain = (j.connection?.domain || "").trim() || null;
|
||||
const geo = {
|
||||
city: j.city || "",
|
||||
region: j.region || "",
|
||||
country: j.country || "",
|
||||
country_code: j.country_code || "",
|
||||
lat: typeof j.latitude === "number" ? j.latitude : null,
|
||||
lon: typeof j.longitude === "number" ? j.longitude : null,
|
||||
};
|
||||
|
||||
console.info("[ip] ok", {
|
||||
ip,
|
||||
owner: owner || undefined,
|
||||
domain: domain || undefined,
|
||||
country: geo.country,
|
||||
geo: geo || undefined,
|
||||
duration_ms: Date.now() - startedAt,
|
||||
});
|
||||
return { geo, owner, domain };
|
||||
} catch {
|
||||
console.warn("[ip] error", { ip });
|
||||
return {
|
||||
owner: null,
|
||||
domain: null,
|
||||
geo: {
|
||||
city: "",
|
||||
region: "",
|
||||
country: "",
|
||||
country_code: "",
|
||||
lat: null,
|
||||
lon: null,
|
||||
emoji: null,
|
||||
},
|
||||
owner: null,
|
||||
domain: null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user