mirror of
https://github.com/hamster1963/nezha-dash.git
synced 2025-04-24 21:10:45 +08:00
feat: get ip info
This commit is contained in:
parent
f28f559a0b
commit
b573b62452
@ -5,12 +5,23 @@ 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 { use, useState } from "react";
|
import GetIPInfo from "@/lib/GetIPInfo";
|
||||||
|
import { use, useEffect, useState } from "react";
|
||||||
|
|
||||||
export default function Page(props: { params: Promise<{ id: string }> }) {
|
export default function Page(props: { params: Promise<{ id: string }> }) {
|
||||||
const params = use(props.params);
|
const params = use(props.params);
|
||||||
const tabs = ["Detail", "Network"];
|
const tabs = ["Detail", "Network"];
|
||||||
const [currentTab, setCurrentTab] = useState(tabs[0]);
|
const [currentTab, setCurrentTab] = useState(tabs[0]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const updateViews = async () => {
|
||||||
|
const ipInfo = await GetIPInfo({ server_id: params.id });
|
||||||
|
console.log(ipInfo);
|
||||||
|
}
|
||||||
|
updateViews()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
|
||||||
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)} />
|
||||||
|
BIN
lib/GeoLite2-ASN.mmdb
Normal file
BIN
lib/GeoLite2-ASN.mmdb
Normal file
Binary file not shown.
BIN
lib/GeoLite2-City.mmdb
Normal file
BIN
lib/GeoLite2-City.mmdb
Normal file
Binary file not shown.
After Width: | Height: | Size: 56 MiB |
22
lib/GetIPInfo.ts
Normal file
22
lib/GetIPInfo.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
"use server";
|
||||||
|
|
||||||
|
import maxmind, { CityResponse, AsnResponse } from 'maxmind';
|
||||||
|
import { GetServerIP } from './serverFetch';
|
||||||
|
|
||||||
|
type IPInfo = {
|
||||||
|
city: CityResponse;
|
||||||
|
asn: AsnResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function GetIPInfo({ server_id }: { server_id: string }): Promise<IPInfo> {
|
||||||
|
|
||||||
|
const ip = await GetServerIP({ server_id: Number(server_id) })
|
||||||
|
|
||||||
|
const cityLookup = await maxmind.open<CityResponse>('./lib/GeoLite2-City.mmdb')
|
||||||
|
const asnLookup = await maxmind.open<AsnResponse>('./lib/GeoLite2-ASN.mmdb')
|
||||||
|
|
||||||
|
return {
|
||||||
|
city: cityLookup.get(ip) as CityResponse,
|
||||||
|
asn: asnLookup.get(ip) as AsnResponse
|
||||||
|
}
|
||||||
|
}
|
@ -130,6 +130,57 @@ export async function GetServerMonitor({ server_id }: { server_id: number }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function GetServerIP({ server_id }: { server_id: number }): Promise<string> {
|
||||||
|
let nezhaBaseUrl = getEnv("NezhaBaseUrl");
|
||||||
|
if (!nezhaBaseUrl) {
|
||||||
|
console.error("NezhaBaseUrl is not set");
|
||||||
|
throw new Error("NezhaBaseUrl is not set");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove trailing slash
|
||||||
|
nezhaBaseUrl = nezhaBaseUrl.replace(/\/$/, "");
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${nezhaBaseUrl}/api/v1/server/details`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: getEnv("NezhaAuth") as string,
|
||||||
|
},
|
||||||
|
next: {
|
||||||
|
revalidate: 0,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const errorText = await response.text();
|
||||||
|
throw new Error(`Failed to fetch data: ${response.status} ${errorText}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const resData = await response.json();
|
||||||
|
|
||||||
|
if (!resData.result) {
|
||||||
|
throw new Error("NezhaData fetch failed: 'result' field is missing");
|
||||||
|
}
|
||||||
|
|
||||||
|
const nezhaData = resData.result as NezhaAPI[];
|
||||||
|
|
||||||
|
// Find the server with the given ID
|
||||||
|
const server = nezhaData.find((element) => element.id === server_id);
|
||||||
|
|
||||||
|
if (!server) {
|
||||||
|
throw new Error(`Server with ID ${server_id} not found`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return server?.valid_ip || server?.ipv4 || server?.ipv6 || "";
|
||||||
|
} catch (error) {
|
||||||
|
console.error("GetNezhaData error:", error);
|
||||||
|
throw error; // Rethrow the error to be caught by the caller
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export async function GetServerDetail({ server_id }: { server_id: number }) {
|
export async function GetServerDetail({ server_id }: { server_id: number }) {
|
||||||
let nezhaBaseUrl = getEnv("NezhaBaseUrl");
|
let nezhaBaseUrl = getEnv("NezhaBaseUrl");
|
||||||
if (!nezhaBaseUrl) {
|
if (!nezhaBaseUrl) {
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
"framer-motion": "^12.0.0-alpha.2",
|
"framer-motion": "^12.0.0-alpha.2",
|
||||||
"lucide-react": "^0.454.0",
|
"lucide-react": "^0.454.0",
|
||||||
"luxon": "^3.5.0",
|
"luxon": "^3.5.0",
|
||||||
|
"maxmind": "^4.3.23",
|
||||||
"next": "^15.1.0",
|
"next": "^15.1.0",
|
||||||
"next-auth": "^5.0.0-beta.25",
|
"next-auth": "^5.0.0-beta.25",
|
||||||
"next-intl": "^3.26.0",
|
"next-intl": "^3.26.0",
|
||||||
|
Loading…
Reference in New Issue
Block a user