diff --git a/package.json b/package.json index 37c6a98..40f2ea8 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", "lucide-react": "^0.368.0", - "mcutils-library": "^1.1.5", + "mcutils-library": "^1.2.1", "next": "14.2.1", "next-themes": "^0.3.0", "react": "^18", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 21cda8a..e7f51f2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -21,8 +21,8 @@ dependencies: specifier: ^0.368.0 version: 0.368.0(react@18.2.0) mcutils-library: - specifier: ^1.1.5 - version: 1.1.5(@babel/core@7.24.4)(@types/node@20.12.7) + specifier: ^1.2.1 + version: 1.2.1(@babel/core@7.24.4)(@types/node@20.12.7) next: specifier: 14.2.1 version: 14.2.1(@babel/core@7.24.4)(react-dom@18.2.0)(react@18.2.0) @@ -3516,8 +3516,8 @@ packages: tmpl: 1.0.5 dev: false - /mcutils-library@1.1.5(@babel/core@7.24.4)(@types/node@20.12.7): - resolution: {integrity: sha512-aQCn4YLvmkoqc+yClLiiiNkPJ+02iSOxzZ5X+Tr0SPPNhNzHn6IAP71ZS3SGQlLeRkfIqXynjbhrEplmW+CBzw==} + /mcutils-library@1.2.1(@babel/core@7.24.4)(@types/node@20.12.7): + resolution: {integrity: sha512-5OZP5MfZnVg/72gPvH88Fg45KQKe0z2S/1sGBOi3Tv9CxYDJJIYE7FWjHLgiRPFm2keY0P+RZlcZ2Zs3OvOpGQ==} dependencies: axios: 1.6.8 jest: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2) diff --git a/src/app/(pages)/mojang/page.tsx b/src/app/(pages)/mojang/page.tsx index fbbf576..2d72758 100644 --- a/src/app/(pages)/mojang/page.tsx +++ b/src/app/(pages)/mojang/page.tsx @@ -3,8 +3,7 @@ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@ import { generateEmbed } from "@/common/embed"; import { capitalizeFirstLetter } from "@/common/string-utils"; import { cn } from "@/common/utils"; -import { getMojangEndpointStatus } from "mcutils-library"; -import { CachedEndpointStatus } from "mcutils-library/dist/types/cache/cachedEndpointStatus"; +import { CachedEndpointStatus, getMojangEndpointStatus } from "mcutils-library"; import { Metadata } from "next"; import Link from "next/link"; diff --git a/src/app/(pages)/page.tsx b/src/app/(pages)/page.tsx index 7b26943..a4b692e 100644 --- a/src/app/(pages)/page.tsx +++ b/src/app/(pages)/page.tsx @@ -6,7 +6,7 @@ type Button = { }; const buttons: Button[] = [ - { title: "Get Started", url: "/player/Notch" }, + { title: "Get Started", url: "/player" }, { title: "Documentation", url: "https://api.mcutils.xyz/swagger-ui.html" }, ]; diff --git a/src/app/(pages)/player/[id]/page.tsx b/src/app/(pages)/player/[[...id]]/page.tsx similarity index 58% rename from src/app/(pages)/player/[id]/page.tsx rename to src/app/(pages)/player/[[...id]]/page.tsx index 43bc7ae..d5e40d8 100644 --- a/src/app/(pages)/player/[id]/page.tsx +++ b/src/app/(pages)/player/[[...id]]/page.tsx @@ -1,12 +1,9 @@ /* eslint-disable @next/next/no-img-element */ import { Card } from "@/app/components/card"; -import { NotFound } from "@/app/components/not-found"; +import { ErrorCard } from "@/app/components/error-card"; import { LookupPlayer } from "@/app/components/player/lookup-player"; import { generateEmbed } from "@/common/embed"; -import { getPlayer } from "mcutils-library"; -import { CachedPlayer } from "mcutils-library/dist/types/cache/cachedPlayer"; -import { McUtilsAPIError } from "mcutils-library/dist/types/error"; -import { Player, SkinPart } from "mcutils-library/dist/types/player/player"; +import { CachedPlayer, McUtilsAPIError, SkinPart, getPlayer } from "mcutils-library"; import { Metadata } from "next"; import Image from "next/image"; import Link from "next/link"; @@ -18,57 +15,39 @@ type Params = { }; export async function generateMetadata({ params: { id } }: Params): Promise { - const { error, player } = await fetchPlayer(id); + try { + const player = await getPlayer(id); - if (error && player == undefined) { - return generateEmbed({ title: "Unknown Player", description: error }); - } + const { username, uniqueId, skin } = player; + const headPartUrl = skin.parts.head; - const { username, uniqueId, skin } = player as Player; - const headPartUrl = skin.parts.head; - - const description = ` + const description = ` Username: ${username} UUID: ${uniqueId}`; - return generateEmbed({ - title: `${username}`, - description: description, - image: headPartUrl, - }); -} - -/** - * Gets the player's data from the uuid or username - * - * @param id the player's uuid or username - * @returns the player's data or an error message - */ -async function getData(id: string): Promise { - return await getPlayer(id); -} - -/** - * Fetches the player's data from the uuid or username - * - * @param id the player's uuid or username - * @returns the player's data or an error message - */ -async function fetchPlayer(id: string): Promise<{ error: string | undefined; player: Player | undefined }> { - let error: string | undefined = undefined; - let player: Player | undefined = undefined; - - try { - player = (await getData(id))?.player; + return generateEmbed({ + title: `${username}`, + description: description, + image: headPartUrl, + }); } catch (err) { - error = (err as McUtilsAPIError).message; + return generateEmbed({ + title: "Player Not Found", + description: (err as McUtilsAPIError).message, + }); } - - return { error, player }; } export default async function Page({ params: { id } }: Params): Promise { - const { error, player } = await fetchPlayer(id); + let error: string | undefined = undefined; // The error to display + let player: CachedPlayer | undefined = undefined; // The player to display + + // Try and get the player to display + try { + player = id ? await getPlayer(id) : undefined; + } catch (err) { + error = (err as McUtilsAPIError).message; // Set the error message + } return (
@@ -79,9 +58,9 @@ export default async function Page({ params: { id } }: Params): Promise
- - {error && } - {player != null && ( + {error && } + {player != undefined && ( +
- )} -
+
+ )} ); } diff --git a/src/app/(pages)/server/[platform]/[[...hostname]]/page.tsx b/src/app/(pages)/server/[platform]/[[...hostname]]/page.tsx new file mode 100644 index 0000000..e54d9e3 --- /dev/null +++ b/src/app/(pages)/server/[platform]/[[...hostname]]/page.tsx @@ -0,0 +1,149 @@ +import { Card } from "@/app/components/card"; +import { ErrorCard } from "@/app/components/error-card"; +import { LookupServer } from "@/app/components/server/lookup-server"; +import { generateEmbed } from "@/common/embed"; +import { formatNumber } from "@/common/number-utils"; +import { capitalizeFirstLetter } from "@/common/string-utils"; +import { + CachedBedrockMinecraftServer, + CachedJavaMinecraftServer, + McUtilsAPIError, + ServerPlatform, + getServer, +} from "mcutils-library"; +import { Metadata } from "next"; +import Image from "next/image"; + +type Params = { + params: { + platform: ServerPlatform; + hostname: string; + }; +}; + +/** + * Gets the favicon for a server + * + * @param platform the platform of the server + * @param server the server to get the favicon from + * @returns the favicon url or null if there is no favicon + */ +function getFavicon( + platform: ServerPlatform, + server: CachedJavaMinecraftServer | CachedBedrockMinecraftServer +): string | undefined { + if (platform === ServerPlatform.Bedrock) { + return undefined; + } + server = server as CachedJavaMinecraftServer; + return server.favicon && server.favicon.url; +} + +/** + * Checks if a platform is valid + * + * @param platform the platform to check + * @returns true if the platform is valid, false otherwise + */ +function checkPlatform(platform: ServerPlatform): boolean { + return platform === ServerPlatform.Java || platform === ServerPlatform.Bedrock; +} + +export async function generateMetadata({ params: { platform, hostname } }: Params): Promise { + try { + if (checkPlatform(platform) === false) { + return generateEmbed({ + title: "Server Not Found", + description: "Invalid platform", + }); + } + const server = await getServer(platform, hostname); + const { hostname: serverHostname, players } = server as CachedJavaMinecraftServer | CachedBedrockMinecraftServer; + + const favicon = server ? getFavicon(platform, server) : undefined; + + const description = ` + ${capitalizeFirstLetter(platform)} Server + Hostname: ${serverHostname} + ${players.online}/${players.max} players online`; + + return generateEmbed({ + title: `${serverHostname}`, + description: description, + image: favicon, + }); + } catch (err) { + return generateEmbed({ + title: "Server Not Found", + description: (err as McUtilsAPIError).message, + }); + } +} + +export default async function Page({ params: { platform, hostname } }: Params): Promise { + let error: string | undefined = undefined; // The error to display + let server: CachedJavaMinecraftServer | CachedBedrockMinecraftServer | undefined = undefined; // The server to display + let invalidPlatform = checkPlatform(platform) === false; + + // Try and get the player to display + try { + console.log(platform); + if (invalidPlatform) { + error = "Invalid platform"; // Set the error message + } else { + server = platform && hostname ? await getServer(platform, hostname) : undefined; + } + } catch (err) { + error = (err as McUtilsAPIError).message; // Set the error message + } + + const favicon = server ? getFavicon(platform, server) : undefined; + + return ( +
+
+

Lookup a {invalidPlatform ? "" : capitalizeFirstLetter(platform)} Server

+

You can enter a server hostname to get information about the server.

+ + +
+ + {error && } + {server != null && ( + +
+
+ {favicon && ( +
+ The server's favicon +
+ )} + +
+

{server.hostname}

+
+

+ Players online: {formatNumber(server.players.online)}/{formatNumber(server.players.max)} +

+
+
+
+ +
+ {server.motd.html.map((line, index) => { + return

; + })} +
+
+
+ )} +
+ ); +} diff --git a/src/app/(pages)/server/[platform]/[hostname]/page.tsx b/src/app/(pages)/server/[platform]/[hostname]/page.tsx deleted file mode 100644 index 22f9072..0000000 --- a/src/app/(pages)/server/[platform]/[hostname]/page.tsx +++ /dev/null @@ -1,146 +0,0 @@ -import { Card } from "@/app/components/card"; -import { NotFound } from "@/app/components/not-found"; -import { LookupServer } from "@/app/components/server/lookup-server"; -import { generateEmbed } from "@/common/embed"; -import { formatNumber } from "@/common/number-utils"; -import { capitalizeFirstLetter } from "@/common/string-utils"; -import { getServer } from "mcutils-library"; -import { McUtilsAPIError } from "mcutils-library/dist/types/error"; -import BedrockMinecraftServer from "mcutils-library/dist/types/server/bedrockServer"; -import JavaMinecraftServer from "mcutils-library/dist/types/server/javaServer"; -import { ServerPlatform } from "mcutils-library/dist/types/server/platform"; -import { Metadata } from "next"; -import Image from "next/image"; - -type Params = { - params: { - platform: ServerPlatform; - hostname: string; - }; -}; - -export async function generateMetadata({ params: { platform, hostname } }: Params): Promise { - const { error, server } = await fetchServer(platform, hostname); - - if (error && server == undefined) { - return generateEmbed({ title: "Unknown Server", description: error }); - } - - const { hostname: serverHostname, players } = server as JavaMinecraftServer | BedrockMinecraftServer; - - let favicon = null; // Server favicon - - // Java specific - 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 generateEmbed({ - title: `${serverHostname}`, - description: description, - image: favicon, - }); -} - -/** - * Gets the server's data from the hostname - * - * @param platform the server's platform - * @param hostnamt the server's hostname - * @returns the server's data or an error message - */ -async function getData( - platform: ServerPlatform, - hostname: string -): Promise { - return (await getServer(platform, hostname)).server; -} - -/** - * Fetches the server's data from the hostname - * - * @param platform the server's platform - * @param hostname the server's hostname - * @returns the server's data or an error message - */ -async function fetchServer( - platform: ServerPlatform, - hostname: string -): Promise<{ error: string | undefined; server: JavaMinecraftServer | BedrockMinecraftServer | undefined }> { - let error: string | undefined = undefined; - let server: JavaMinecraftServer | BedrockMinecraftServer | undefined = undefined; - - try { - server = (await getData(platform, hostname)) as JavaMinecraftServer | BedrockMinecraftServer; - } catch (err) { - error = (err as McUtilsAPIError).message; - } - - return { error, server }; -} - -export default async function Page({ params: { platform, hostname } }: Params): Promise { - const { error, server } = await fetchServer(platform, hostname); - - let favicon = null; // Server favicon - - // Java specific - if (server && platform === ServerPlatform.Java) { - const javaServer = server as JavaMinecraftServer; - favicon = javaServer.favicon && javaServer.favicon.url; - } - - return ( -
-
-

Lookup a {capitalizeFirstLetter(platform)} Server

-

You can enter a server hostname to get information about the server.

- - -
- - - {error && } - {server != null && ( -
-
- {favicon && ( -
- The server's favicon -
- )} - -
-

{server.hostname}

-
-

- Players online: {formatNumber(server.players.online)}/{formatNumber(server.players.max)} -

-
-
-
- -
- {server.motd.html.map((line, index) => { - return

; - })} -
-
- )} -
-
- ); -} diff --git a/src/app/components/error-card.tsx b/src/app/components/error-card.tsx new file mode 100644 index 0000000..b42ab3c --- /dev/null +++ b/src/app/components/error-card.tsx @@ -0,0 +1,16 @@ +import { Card } from "./card"; + +type ErrorProps = { + message: string; +}; + +export function ErrorCard({ message }: ErrorProps): JSX.Element { + return ( + +
+

Error

+

{message}

+
+
+ ); +} diff --git a/src/app/components/navbar.tsx b/src/app/components/navbar.tsx index e0c3fe9..5203156 100644 --- a/src/app/components/navbar.tsx +++ b/src/app/components/navbar.tsx @@ -9,8 +9,8 @@ type Page = { }; const pages: Page[] = [ - { title: "Player", url: "/player/Notch" }, - { title: "Server", url: "/server/java/hypixel.net" }, + { title: "Player", url: "/player" }, + { title: "Server", url: "/server/java" }, { title: "Mojang", url: "/mojang" }, ]; diff --git a/src/app/components/not-found.tsx b/src/app/components/not-found.tsx deleted file mode 100644 index 70e87e5..0000000 --- a/src/app/components/not-found.tsx +++ /dev/null @@ -1,12 +0,0 @@ -type NotFoundProps = { - message: string; -}; - -export function NotFound({ message }: NotFoundProps): JSX.Element { - return ( -
-

Not Found

-

{message}

-
- ); -} diff --git a/src/app/components/server/lookup-server.tsx b/src/app/components/server/lookup-server.tsx index 0f16609..44fae1f 100644 --- a/src/app/components/server/lookup-server.tsx +++ b/src/app/components/server/lookup-server.tsx @@ -1,6 +1,6 @@ "use client"; -import { ServerPlatform } from "mcutils-library/dist/types/server/platform"; +import { ServerPlatform } from "mcutils-library"; import { useRouter } from "next/navigation"; import { useState } from "react"; import { Button } from "../ui/button"; diff --git a/src/app/globals.css b/src/app/globals.css index 87be0f2..ff40256 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -12,7 +12,7 @@ --popover-foreground: 240 10% 3.9%; --primary: 142.1 76.2% 36.3%; --primary-foreground: 355.7 100% 97.3%; - --secondary: 0 0% 100%; + --secondary: 5 5% 95%; --secondary-foreground: 240 5.9% 10%; --muted: 240 4.8% 95.9%; --muted-foreground: 240 3.8% 46.1%; @@ -43,7 +43,7 @@ --accent-foreground: 0 0% 98%; --destructive: 0 62.8% 30.6%; --destructive-foreground: 0 85.7% 97.3%; - --border: 240 3.7% 15.9%; + --border: 240 5.9% 30%; --input: 240 3.7% 15.9%; --ring: 142.4 71.8% 29.2%; }