feat: ip info

This commit is contained in:
hamster1963 2024-12-12 10:46:37 +08:00
parent d72cd29446
commit 33d22fa8b3
4 changed files with 107 additions and 9 deletions

View File

@ -15,3 +15,4 @@ NEXT_PUBLIC_CustomDescription=NezhaDash is a dashboard for Nezha.
NEXT_PUBLIC_Links='[{"link":"https://github.com/hamster1963/nezha-dash","name":"GitHub"},{"link":"https://buycoffee.top/coffee","name":"Buycoffee☕"}]' NEXT_PUBLIC_Links='[{"link":"https://github.com/hamster1963/nezha-dash","name":"GitHub"},{"link":"https://buycoffee.top/coffee","name":"Buycoffee☕"}]'
NEXT_PUBLIC_DisableIndex=false NEXT_PUBLIC_DisableIndex=false
NEXT_PUBLIC_ShowTagCount=false NEXT_PUBLIC_ShowTagCount=false
NEXT_PUBLIC_ShowIpInfo=false

View File

@ -1,24 +1,111 @@
"use client"; "use client";
import { IPInfo } from "@/app/api/server-ip/route"; import { IPInfo } from "@/app/api/server-ip/route";
import { Loader } from "@/components/loading/Loader";
import { Card, CardContent } from "@/components/ui/card";
import { nezhaFetcher } from "@/lib/utils"; import { nezhaFetcher } from "@/lib/utils";
import useSWR from "swr"; import useSWRImmutable from "swr/immutable";
export default function ServerIPInfo({ server_id }: { server_id: number }) { export default function ServerIPInfo({ server_id }: { server_id: number }) {
const { data } = useSWR<IPInfo>( const { data } = useSWRImmutable<IPInfo>(
`/api/server-ip?server_id=${server_id}`, `/api/server-ip?server_id=${server_id}`,
nezhaFetcher, nezhaFetcher,
); );
if (!data) { if (!data) {
return <div>Loading...</div>; return (
<div className="mb-11">
<Loader visible />
</div>
);
} }
console.log(data);
return ( return (
<div> <>
<h1>Server IP Info</h1> <section className="flex flex-wrap gap-2 mb-4">
</div> <Card className="rounded-[10px] bg-transparent border-none shadow-none">
<CardContent className="px-1.5 py-1">
<section className="flex flex-col items-start gap-0.5">
<p className="text-xs text-muted-foreground">{"ASN"}</p>
<div className="text-xs">
{data.asn.autonomous_system_organization}
</div>
</section>
</CardContent>
</Card>
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
<CardContent className="px-1.5 py-1">
<section className="flex flex-col items-start gap-0.5">
<p className="text-xs text-muted-foreground">{"Origin ASN"}</p>
<div className="text-xs">
AS{data.asn.autonomous_system_number}
</div>
</section>
</CardContent>
</Card>
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
<CardContent className="px-1.5 py-1">
<section className="flex flex-col items-start gap-0.5">
<p className="text-xs text-muted-foreground">
{"Registered Country"}
</p>
<div className="text-xs">
{data.city.registered_country?.names.en}
</div>
</section>
</CardContent>
</Card>
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
<CardContent className="px-1.5 py-1">
<section className="flex flex-col items-start gap-0.5">
<p className="text-xs text-muted-foreground">{"Time Zone"}</p>
<div className="text-xs">{data.city.location?.time_zone}</div>
</section>
</CardContent>
</Card>
{data.city.postal && (
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
<CardContent className="px-1.5 py-1">
<section className="flex flex-col items-start gap-0.5">
<p className="text-xs text-muted-foreground">{"Postal"}</p>
<div className="text-xs">{data.city.postal?.code}</div>
</section>
</CardContent>
</Card>
)}
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
<CardContent className="px-1.5 py-1">
<section className="flex flex-col items-start gap-0.5">
<p className="text-xs text-muted-foreground">{"ISO"}</p>
<div className="text-xs">{data.city.country?.iso_code}</div>
</section>
</CardContent>
</Card>
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
<CardContent className="px-1.5 py-1">
<section className="flex flex-col items-start gap-0.5">
<p className="text-xs text-muted-foreground">{"City"}</p>
<div className="text-xs">{data.city.city?.names.en}</div>
</section>
</CardContent>
</Card>
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
<CardContent className="px-1.5 py-1">
<section className="flex flex-col items-start gap-0.5">
<p className="text-xs text-muted-foreground">{"Longitude"}</p>
<div className="text-xs">{data.city.location?.longitude}</div>
</section>
</CardContent>
</Card>
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
<CardContent className="px-1.5 py-1">
<section className="flex flex-col items-start gap-0.5">
<p className="text-xs text-muted-foreground">{"Latitude"}</p>
<div className="text-xs">{data.city.location?.latitude}</div>
</section>
</CardContent>
</Card>
</section>
</>
); );
} }

View File

@ -5,6 +5,7 @@ import ServerDetailChartClient from "@/app/(main)/ClientComponents/ServerDetailC
import ServerDetailClient from "@/app/(main)/ClientComponents/ServerDetailClient"; import ServerDetailClient from "@/app/(main)/ClientComponents/ServerDetailClient";
import TabSwitch from "@/components/TabSwitch"; import TabSwitch from "@/components/TabSwitch";
import { Separator } from "@/components/ui/separator"; import { Separator } from "@/components/ui/separator";
import getEnv from "@/lib/env-entry";
import { use, useState } from "react"; import { use, useState } from "react";
import ServerIPInfo from "../../ClientComponents/ServerIPInfo"; import ServerIPInfo from "../../ClientComponents/ServerIPInfo";
@ -16,7 +17,6 @@ export default function Page(props: { params: Promise<{ id: string }> }) {
return ( return (
<div className="mx-auto grid w-full max-w-5xl gap-2"> <div className="mx-auto grid w-full max-w-5xl gap-2">
<ServerDetailClient server_id={Number(params.id)} /> <ServerDetailClient server_id={Number(params.id)} />
<ServerIPInfo server_id={Number(params.id)} />
<section className="flex items-center my-2 w-full"> <section className="flex items-center my-2 w-full">
<Separator className="flex-1" /> <Separator className="flex-1" />
<div className="flex justify-center w-full max-w-[200px]"> <div className="flex justify-center w-full max-w-[200px]">
@ -35,6 +35,9 @@ export default function Page(props: { params: Promise<{ id: string }> }) {
/> />
</div> </div>
<div style={{ display: currentTab === tabs[1] ? "block" : "none" }}> <div style={{ display: currentTab === tabs[1] ? "block" : "none" }}>
{getEnv("NEXT_PUBLIC_ShowIpInfo") && (
<ServerIPInfo server_id={Number(params.id)} />
)}
<NetworkChartClient <NetworkChartClient
server_id={Number(params.id)} server_id={Number(params.id)}
show={currentTab === tabs[1]} show={currentTab === tabs[1]}

View File

@ -27,6 +27,13 @@ export async function GET(req: NextRequest) {
} }
} }
if (!getEnv("NEXT_PUBLIC_ShowIpInfo")) {
return NextResponse.json(
{ error: "NEXT_PUBLIC_ShowIpInfo is disable" },
{ status: 400 },
);
}
const { searchParams } = new URL(req.url); const { searchParams } = new URL(req.url);
const server_id = searchParams.get("server_id"); const server_id = searchParams.get("server_id");