recode most things - still wip
All checks were successful
Deploy App / docker (ubuntu-latest) (push) Successful in 2m0s

This commit is contained in:
Lee 2024-04-16 17:54:22 +01:00
parent c054a31008
commit 59acc3a7db
13 changed files with 205 additions and 209 deletions

View File

@ -0,0 +1,46 @@
import { NotFound } from "@/components/not-found";
import { Card } from "@/components/ui/card";
import { getPlayer } from "mcutils-library";
import { Player } from "mcutils-library/dist/types/player/player";
import { Metadata } from "next";
export const metadata: Metadata = {
title: "Lookup Player",
};
async function getData(id: string): Promise<Player | null> {
try {
const cachedPlayer = await getPlayer(id);
return cachedPlayer.player;
} catch (error) {
return null; // Player not found
}
}
type Params = {
params: {
id: string;
};
};
export default async function Page({ params }: Params) {
const player = await getData(params.id);
return (
<div className="h-full flex flex-col items-center">
<div className="mb-4 text-center">
<h1 className="text-xl">Lookup a Player</h1>
<p>You can enter a players uuid or username to get information about the player.</p>
</div>
<Card>
{player == null && <NotFound message="Player not found" />}
{player != null && (
<div className="flex flex-col items-center gap-2">
<p>Username: {player.username}</p>
</div>
)}
</Card>
</div>
);
}

View File

@ -1,18 +0,0 @@
import PlayerSearch from "@/components/player-search";
import { Metadata } from "next";
export const metadata: Metadata = {
title: "Lookup Player",
};
export default function Player() {
return (
<div className="h-full flex flex-col items-center">
<div className="mb-4 text-center">
<h1 className="text-xl">Lookup a Player</h1>
<p>You can enter a players uuid or username to get information about the player.</p>
</div>
<PlayerSearch />
</div>
);
}

View File

@ -0,0 +1,88 @@
import { capitalizeFirstLetter } from "@/common/string-utils";
import { LookupServer } from "@/components/lookup-server";
import { NotFound } from "@/components/not-found";
import { Card } from "@/components/ui/card";
import { getServer } from "mcutils-library";
import JavaMinecraftServer from "mcutils-library/dist/types/server/javaServer";
import { ServerPlatform } from "mcutils-library/dist/types/server/platform";
import { MinecraftServer } from "mcutils-library/dist/types/server/server";
import { Metadata } from "next";
type Params = {
params: {
platform: ServerPlatform;
hostname: string;
};
};
export async function generateMetadata({ params: { platform, hostname } }: Params): Promise<Metadata> {
const server = await getData(platform, hostname);
if (!server) {
return {
title: "Unknown Server",
};
}
const { hostname: serverHostname, players } = server;
let favicon = null;
if (platform === ServerPlatform.Java) {
const javaServer = server as JavaMinecraftServer;
favicon = javaServer.favicon && javaServer.favicon.url;
}
const description = `
${capitalizeFirstLetter(platform)} Server
Hostname: ${serverHostname}
${players.online}/${players.max} players online`;
return {
title: `${hostname}`,
openGraph: {
title: `${hostname}`,
description: description,
images: [
{
url: favicon || "",
},
],
},
twitter: {
card: "summary",
},
};
}
async function getData(platform: ServerPlatform, id: string): Promise<MinecraftServer | null> {
console.log(platform, id);
try {
const cachedServer = await getServer(platform, id);
return cachedServer.server;
} catch (error) {
return null; // Server not found
}
}
export default async function Page({ params: { platform, hostname } }: Params) {
const server = await getData(platform, hostname);
return (
<div className="h-full flex flex-col items-center">
<div className="mb-4 text-center">
<h1 className="text-xl">Lookup a Server</h1>
<p>You can enter a server hostname to get information about the server.</p>
<LookupServer />
</div>
<Card>
{server == null && <NotFound message="Server not found" />}
{server != null && (
<div className="flex flex-col items-center gap-2">
<p>Hostname: {server.hostname}</p>
</div>
)}
</Card>
</div>
);
}

View File

@ -1,18 +0,0 @@
import ServerSearch from "@/components/server-search";
import { Metadata } from "next";
export const metadata: Metadata = {
title: "Lookup Server",
};
export default function Server() {
return (
<div className="h-full flex flex-col items-center">
<div className="mb-4 text-center">
<h1 className="text-xl">Lookup a Server</h1>
<p>You can enter a server ip or domain to get information about the server.</p>
</div>
<ServerSearch />
</div>
);
}

View File

@ -0,0 +1,9 @@
/**
* Capitalizes the first letter of a string
*
* @param str the string to change
* @returns the updated string
*/
export function capitalizeFirstLetter(str: string) {
return str.charAt(0).toUpperCase() + str.slice(1);
}

View File

@ -0,0 +1,9 @@
import { Card } from "./ui/card";
export function LoadingCard() {
return (
<Card>
<p>Loading...</p>
</Card>
);
}

View File

@ -0,0 +1,38 @@
"use client";
import { ServerPlatform } from "mcutils-library/dist/types/server/platform";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { Button } from "./ui/button";
import { Input } from "./ui/input";
export function LookupServer() {
const router = useRouter();
const [hostname, setHostname] = useState("");
/**
* Set the hostname value
*
* @param event the input event
*/
const setHostnameValue = (event: React.ChangeEvent<HTMLInputElement>) => {
setHostname(event.target.value);
};
/**
* Lookup a server based on the platform
*
* @param platform the server platform
*/
const lookupServer = (platform: ServerPlatform) => {
router.push(`/server/${platform}/${hostname}`);
};
return (
<div className="flex gap-2 justify-center mt-2">
<Input className="w-fit" placeholder="Server hostname" value={hostname} onChange={setHostnameValue} />
<Button onClick={() => lookupServer(ServerPlatform.Java)}>Java</Button>
<Button onClick={() => lookupServer(ServerPlatform.Bedrock)}>Bedrock</Button>
</div>
);
}

View File

@ -7,8 +7,8 @@ type Page = {
};
const pages: Page[] = [
{ title: "Player", url: "/player" },
{ title: "Server", url: "/server" },
{ title: "Player", url: "/player/Notch" },
{ title: "Server", url: "/server/java/hypixel.net" },
];
export default function NavBar() {

View File

@ -0,0 +1,12 @@
type NotFoundProps = {
message: string;
};
export function NotFound({ message }: NotFoundProps) {
return (
<div className="flex flex-col justify-center text-center">
<h1 className="text-xl text-red-400">Not Found</h1>
<p>{message}</p>
</div>
);
}

View File

@ -1,87 +0,0 @@
"use client";
import { getPlayer } from "mcutils-library";
import { Player } from "mcutils-library/dist/types/player/player";
import Image from "next/image";
import Link from "next/link";
import { useState } from "react";
import { toast } from "react-toastify";
import { Button } from "./ui/button";
import { Card } from "./ui/card";
import { Input } from "./ui/input";
const defaultPlayerId = "Notch";
export default function PlayerSearch() {
const [playerId, setPlayerId] = useState<string>(defaultPlayerId);
const [player, setPlayer] = useState<Player | null>(null);
const handleLookup = async () => {
if (playerId === null || playerId.length <= 0) {
toast.error("Please enter a player ID");
return;
}
try {
const cachedPlayer = await getPlayer(playerId);
const { player } = cachedPlayer;
setPlayer(player);
} catch (error) {
toast.error("Unknown player");
return;
}
};
const handleKeyDown = (e: any) => {
if (e.key === "Enter") {
handleLookup();
}
};
return (
<div className="flex flex-col items-center gap-8">
<div className="flex items-center gap-2">
<Input
className="w-[200px]"
placeholder="Player ID"
defaultValue={defaultPlayerId}
onChange={(e) => setPlayerId(e.target.value)}
onKeyDown={handleKeyDown}
/>
<Button onClick={() => handleLookup()}>Lookup</Button>
</div>
{player && (
<Card>
<div className="w-full flex flex-col md:flex-row gap-2">
<div className="flex justify-center">
<Image src={player.skin.parts.head} alt="The player's Head" width={150} height={150} />
</div>
<div className="flex flex-col gap-1 mt-2">
<p>
UUID: <span className="font-bold">{player.uniqueId}</span>
</p>
<p>
Name: <span className="font-bold">{player.username}</span>
</p>
<div className="mt-2">
<p>Skin Parts</p>
<div className="flex gap-2">
{Object.keys(player.skin.parts).map((part: any, index: number) => {
return (
<p key={index}>
<Link className="text-primary" href={player.skin.parts[part]} target="_blank">
{part}
</Link>
</p>
);
})}
</div>
</div>
</div>
</div>
</Card>
)}
</div>
);
}

View File

@ -1,82 +0,0 @@
"use client";
import { cn } from "@/common/utils";
import { getServer } from "mcutils-library";
import JavaMinecraftServer from "mcutils-library/dist/types/server/javaServer";
import { ServerPlatform } from "mcutils-library/dist/types/server/platform";
import Image from "next/image";
import { useState } from "react";
import { toast } from "react-toastify";
import { Button } from "./ui/button";
import { Card } from "./ui/card";
import { Input } from "./ui/input";
const defaultServerHostname = "play.hypixel.net";
export default function ServerSearch() {
const [serverHostname, setServerHostname] = useState<string>(defaultServerHostname);
const [server, setServer] = useState<JavaMinecraftServer | null>(null);
const handleLookup = async () => {
if (serverHostname === null || serverHostname.length <= 0) {
toast.error("Please enter a server hostname");
return;
}
try {
const cachedServer = await getServer(ServerPlatform.Java, serverHostname);
const { server } = cachedServer;
setServer(server as JavaMinecraftServer);
} catch (error) {
toast.error("Unknown server");
return;
}
};
const handleKeyDown = (e: any) => {
if (e.key === "Enter") {
handleLookup();
}
};
return (
<div className="flex flex-col items-center gap-8">
<div className="flex items-center gap-2">
<Input
className="w-[200px]"
placeholder="Server Domain or IP"
defaultValue={defaultServerHostname}
onChange={(e) => setServerHostname(e.target.value)}
onKeyDown={handleKeyDown}
/>
<Button onClick={() => handleLookup()}>Lookup</Button>
</div>
{server && (
<Card>
<div className="w-full flex flex-col gap-2">
<div className="flex flex-col md:flex-row gap-2">
<div className="flex justify-center">
<Image src={server.favicon.url} alt="The server's Favicon" width={64} height={64} />
</div>
<div className={cn("flex flex-col gap-2")}>
{server.motd.html.map((line, index) => {
return <div key={index} dangerouslySetInnerHTML={{ __html: line }} />;
})}
</div>
</div>
<div className="flex flex-col gap-1">
<div>
<span className="font-bold">Host:</span> {server.hostname}
</div>
<div>
<span className="font-bold">Players:</span> {server.players.online}/{server.players.max}
</div>
</div>
</div>
</Card>
)}
</div>
);
}

View File

@ -3,5 +3,5 @@ export function Card({
}: Readonly<{
children: React.ReactNode;
}>) {
return <div className="bg-secondary rounded-lg p-4 w-full">{children}</div>;
return <div className="bg-secondary rounded-lg p-4">{children}</div>;
}

View File

@ -1 +0,0 @@
export const API_ENDPOINT = "https://api.mcutils.xyz";