mirror of
https://github.com/hamster1963/nezha-dash.git
synced 2025-04-24 21:10:45 +08:00
feat: use api
This commit is contained in:
parent
d64683a617
commit
4036c157c9
24
app/(main)/ClientComponents/ServerIPInfo.tsx
Normal file
24
app/(main)/ClientComponents/ServerIPInfo.tsx
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { IPInfo } from "@/app/api/server-ip/route";
|
||||||
|
import { nezhaFetcher } from "@/lib/utils";
|
||||||
|
import useSWR from "swr";
|
||||||
|
|
||||||
|
export default function ServerIPInfo({ server_id }: { server_id: number }) {
|
||||||
|
const { data } = useSWR<IPInfo>(
|
||||||
|
`/api/server-ip?server_id=${server_id}`,
|
||||||
|
nezhaFetcher,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
return <div>Loading...</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(data);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1>Server IP Info</h1>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -5,25 +5,18 @@ 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 GetIPInfo from "@/lib/GetIPInfo";
|
|
||||||
import { use, useEffect, useState } from "react";
|
import { use, useEffect, useState } from "react";
|
||||||
|
|
||||||
|
import ServerIPInfo from "../../ClientComponents/ServerIPInfo";
|
||||||
|
|
||||||
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)} />
|
||||||
|
<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]">
|
||||||
|
65
app/api/server-ip/route.ts
Normal file
65
app/api/server-ip/route.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import { auth } from "@/auth";
|
||||||
|
import getEnv from "@/lib/env-entry";
|
||||||
|
import { GetServerIP } from "@/lib/serverFetch";
|
||||||
|
import fs from "fs";
|
||||||
|
import { AsnResponse, CityResponse, Reader } from "maxmind";
|
||||||
|
import { redirect } from "next/navigation";
|
||||||
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
|
interface ResError extends Error {
|
||||||
|
statusCode: number;
|
||||||
|
message: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type IPInfo = {
|
||||||
|
city: CityResponse;
|
||||||
|
asn: AsnResponse;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function GET(req: NextRequest) {
|
||||||
|
if (getEnv("SitePassword")) {
|
||||||
|
const session = await auth();
|
||||||
|
if (!session) {
|
||||||
|
redirect("/");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { searchParams } = new URL(req.url);
|
||||||
|
const server_id = searchParams.get("server_id");
|
||||||
|
|
||||||
|
if (!server_id) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "server_id is required" },
|
||||||
|
{ status: 400 },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const ip = await GetServerIP({ server_id: Number(server_id) });
|
||||||
|
|
||||||
|
const cityDbPath = path.join(process.cwd(), "lib", "GeoLite2-City.mmdb");
|
||||||
|
|
||||||
|
const asnDbPath = path.join(process.cwd(), "lib", "GeoLite2-ASN.mmdb");
|
||||||
|
|
||||||
|
const cityDbBuffer = fs.readFileSync(cityDbPath);
|
||||||
|
const asnDbBuffer = fs.readFileSync(asnDbPath);
|
||||||
|
|
||||||
|
const cityLookup = new Reader<CityResponse>(cityDbBuffer);
|
||||||
|
const asnLookup = new Reader<AsnResponse>(asnDbBuffer);
|
||||||
|
|
||||||
|
const data: IPInfo = {
|
||||||
|
city: cityLookup.get(ip) as CityResponse,
|
||||||
|
asn: asnLookup.get(ip) as AsnResponse,
|
||||||
|
};
|
||||||
|
return NextResponse.json(data, { status: 200 });
|
||||||
|
} catch (error) {
|
||||||
|
const err = error as ResError;
|
||||||
|
console.error("Error in GET handler:", err);
|
||||||
|
const statusCode = err.statusCode || 500;
|
||||||
|
const message = err.message || "Internal Server Error";
|
||||||
|
return NextResponse.json({ error: message }, { status: statusCode });
|
||||||
|
}
|
||||||
|
}
|
@ -1,35 +0,0 @@
|
|||||||
"use server";
|
|
||||||
|
|
||||||
import fs from "fs";
|
|
||||||
import path from 'path';
|
|
||||||
import { AsnResponse, CityResponse, Reader } 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 cityDbPath = path.join(process.cwd(),"lib", 'GeoLite2-City.mmdb');
|
|
||||||
|
|
||||||
const asnDbPath = path.join(process.cwd(),"lib", 'GeoLite2-ASN.mmdb');
|
|
||||||
|
|
||||||
const cityDbBuffer = fs.readFileSync(cityDbPath);
|
|
||||||
const asnDbBuffer = fs.readFileSync(asnDbPath);
|
|
||||||
|
|
||||||
const cityLookup = new Reader<CityResponse>(cityDbBuffer);
|
|
||||||
const asnLookup = new Reader<AsnResponse>(asnDbBuffer);
|
|
||||||
|
|
||||||
return {
|
|
||||||
city: cityLookup.get(ip) as CityResponse,
|
|
||||||
asn: asnLookup.get(ip) as AsnResponse,
|
|
||||||
};
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user