feat: allow server banners to have any URL

This commit is contained in:
dvelo 2024-11-10 20:57:08 -06:00
parent 082036eda4
commit a6c1404646
7 changed files with 211 additions and 160 deletions

@ -105,6 +105,7 @@
"react-markdown": "^9.0.1", "react-markdown": "^9.0.1",
"react-resizable-panels": "^2.0.23", "react-resizable-panels": "^2.0.23",
"recharts": "^2.12.7", "recharts": "^2.12.7",
"shiki": "^1.22.2",
"tailwindcss": "^3.4.1", "tailwindcss": "^3.4.1",
"typescript": "^5", "typescript": "^5",
"vaul": "^0.9.1", "vaul": "^0.9.1",

@ -161,7 +161,16 @@ export default function AfterServerView({ server }: { server: string }) {
{description != "" && view == "desc" && ( {description != "" && view == "desc" && (
<Card className="sm:col-span-3"> <Card className="sm:col-span-3">
<CardDescription className="p-4 prose dark:prose-invert"> <CardDescription className="p-4 prose dark:prose-invert">
<Markdown disallowedElements={["img"]}> <Markdown
components={{
img(props) {
// wsrv.nl caches images for us AND protects the IP's of users
return (
<img src={`//wsrv.nl/?url=${props.src}`} {...props} />
);
},
}}
>
{description} {description}
</Markdown> </Markdown>
</CardDescription> </CardDescription>

@ -59,8 +59,13 @@ export default function Banner({ server }: { server: string }) {
<> <>
{bannerURL != "" && ( {bannerURL != "" && (
<img <img
src={"https://i.imgur.com/" + bannerURL} src={
bannerURL.startsWith("https://i.imgur.com")
? bannerURL
: "wsrv.nl/?url=" + encodeURIComponent(bannerURL) + "?n=-1"
}
className="rounded align-middle block ml-auto mr-auto w-[50%] max-h-[150px]" className="rounded align-middle block ml-auto mr-auto w-[50%] max-h-[150px]"
alt="User-provided banner for this server."
/> />
)} )}
<br /> <br />

@ -181,7 +181,7 @@ export default function ServerCustomize({
Is this server in violation of the ECA? Is this server in violation of the ECA?
</div> </div>
Is this server in violation of the{" "} Is this server in violation of the{" "}
<Link href="/src/app/(main)/docs/legal/external-content-agreement"> <Link href="/docs/legal/external-content-agreement">
External Content Agreement (aka ECA) External Content Agreement (aka ECA)
</Link> </Link>
? You can report the server to remove the customizations from the ? You can report the server to remove the customizations from the
@ -196,7 +196,7 @@ export default function ServerCustomize({
<DialogDescription> <DialogDescription>
This will send a notification to MHSF maintainers. This This will send a notification to MHSF maintainers. This
server must be in violation of the{" "} server must be in violation of the{" "}
<Link href="/src/app/(main)/docs/legal/external-content-agreement"> <Link href="/docs/legal/external-content-agreement">
ECA ECA
</Link>{" "} </Link>{" "}
to be a valid report. Typical response times include 1 hour to be a valid report. Typical response times include 1 hour
@ -329,7 +329,7 @@ export default function ServerCustomize({
Minehuts Terms of Service Minehuts Terms of Service
</Link>{" "} </Link>{" "}
& the{" "} & the{" "}
<Link href="/src/app/(main)/docs/legal/external-content-agreement"> <Link href="/docs/legal/external-content-agreement">
External Content Agreement External Content Agreement
</Link> </Link>
. .
@ -436,7 +436,7 @@ export default function ServerCustomize({
Imgurs Terms of Service Imgurs Terms of Service
</Link>{" "} </Link>{" "}
& the{" "} & the{" "}
<Link href="/src/app/(main)/docs/legal/external-content-agreement"> <Link href="/docs/legal/external-content-agreement">
External Content Agreement External Content Agreement
</Link> </Link>
. .
@ -468,7 +468,7 @@ export default function ServerCustomize({
Discords Terms of Service Discords Terms of Service
</Link>{" "} </Link>{" "}
& the{" "} & the{" "}
<Link href="/src/app/(main)/docs/legal/external-content-agreement"> <Link href="/docs/legal/external-content-agreement">
External Content Agreement External Content Agreement
</Link> </Link>
. .

@ -1,33 +1,3 @@
/*
* MHSF, Minehut Server List
* All external content is rather licensed under the ECA Agreement
* located here: https://list.mlnehut.com/docs/legal/external-content-agreement
*
* All code under MHSF is licensed under the MIT License
* by open source contributors
*
* Copyright (c) 2024 dvelo
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
"use client"; "use client";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
@ -46,8 +16,8 @@ import {
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { setCustomization } from "@/lib/api"; import { setCustomization } from "@/lib/api";
import { useEffect } from "react"; import { useEffect } from "react";
import ColorProvider from "../ColorProvider";
import toast from "react-hot-toast"; import toast from "react-hot-toast";
import ColorProvider from "../ColorProvider";
const FormSchema = z.object({ const FormSchema = z.object({
website: z website: z
@ -67,43 +37,27 @@ export function BannerPopover({ server, get }: { server: string; get: any }) {
}); });
async function onSubmit(data: z.infer<typeof FormSchema>) { async function onSubmit(data: z.infer<typeof FormSchema>) {
if (data.website.startsWith("https://i.imgur.com")) {
let imageId = data.website.split(".com")[1];
imageId = imageId.substring(1);
toast.promise(setCustomization(server, { banner: imageId }), { toast.promise(setCustomization(server, { banner: imageId }), {
loading: "Setting banner..", loading: "Setting banner..",
success: "Set banner!", success: "Set banner!",
error: "Error while setting banner", error: "Error while setting banner",
}); });
} else {
toast.error(
"To avoid view loggers, the Image URL must be from Imgur. (do not use the generic imgur.com URL, copy the direct image URL with i.imgur.com) "
);
} }
}
useEffect(() => console.log(get.discord), [get]);
return ( return (
<ColorProvider server={server} fetch={get}> <ColorProvider server={server} fetch={get}>
<div> <div>
<span className="text-sm"> <span className="text-sm">
Make sure the image is from Imgur, and the image format is png or gif. All images that are in a web supported format can be used as the
banner for a server.
</span> </span>
<br /> <br />
<br /> <br />
<strong>Tutorial:</strong>
<video width="600" height="600" className="rounded w-[600px]" autoPlay>
<source src="/videos/imgurTutorial.mp4" type="video/mp4" />
</video>
<br />
<br />
<Form {...form}> <Form {...form}>
<form <form
onSubmit={form.handleSubmit(onSubmit)} onSubmit={form.handleSubmit(onSubmit)}
className="w-2/3 space-y-6" className="w-2/3 space-y-6"
defaultValue={get.discord} defaultValue={get?.banner}
> >
<FormField <FormField
control={form.control} control={form.control}

@ -62,12 +62,6 @@ export default async function handler(
) )
return res.status(400).send({ message: "Description is incorrect length" }); return res.status(400).send({ message: "Description is incorrect length" });
if (
customization.banner != undefined &&
!(Array.from(customization.banner).length > 5)
)
return res.status(400).send({ message: "Banner is incorrect length" });
if ( if (
customization.discord != undefined && customization.discord != undefined &&
!/^\d*\.?\d*$/.test(customization.discord) !/^\d*\.?\d*$/.test(customization.discord)

@ -1969,6 +1969,48 @@
resolved "https://registry.yarnpkg.com/@sapphire/snowflake/-/snowflake-3.5.3.tgz#0c102aa2ec5b34f806e9bc8625fc6a5e1d0a0c6a" resolved "https://registry.yarnpkg.com/@sapphire/snowflake/-/snowflake-3.5.3.tgz#0c102aa2ec5b34f806e9bc8625fc6a5e1d0a0c6a"
integrity sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ== integrity sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==
"@shikijs/core@1.22.2":
version "1.22.2"
resolved "https://registry.yarnpkg.com/@shikijs/core/-/core-1.22.2.tgz#9c22bd4cc8a4d6c062461cfd35e1faa6c617ca25"
integrity sha512-bvIQcd8BEeR1yFvOYv6HDiyta2FFVePbzeowf5pPS1avczrPK+cjmaxxh0nx5QzbON7+Sv0sQfQVciO7bN72sg==
dependencies:
"@shikijs/engine-javascript" "1.22.2"
"@shikijs/engine-oniguruma" "1.22.2"
"@shikijs/types" "1.22.2"
"@shikijs/vscode-textmate" "^9.3.0"
"@types/hast" "^3.0.4"
hast-util-to-html "^9.0.3"
"@shikijs/engine-javascript@1.22.2":
version "1.22.2"
resolved "https://registry.yarnpkg.com/@shikijs/engine-javascript/-/engine-javascript-1.22.2.tgz#62e90dbd2ed1d78b972ad7d0a1f8ffaaf5e43279"
integrity sha512-iOvql09ql6m+3d1vtvP8fLCVCK7BQD1pJFmHIECsujB0V32BJ0Ab6hxk1ewVSMFA58FI0pR2Had9BKZdyQrxTw==
dependencies:
"@shikijs/types" "1.22.2"
"@shikijs/vscode-textmate" "^9.3.0"
oniguruma-to-js "0.4.3"
"@shikijs/engine-oniguruma@1.22.2":
version "1.22.2"
resolved "https://registry.yarnpkg.com/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.2.tgz#b12a44e3faf486e19fbcf8952f4b56b9b9b8d9b8"
integrity sha512-GIZPAGzQOy56mGvWMoZRPggn0dTlBf1gutV5TdceLCZlFNqWmuc7u+CzD0Gd9vQUTgLbrt0KLzz6FNprqYAxlA==
dependencies:
"@shikijs/types" "1.22.2"
"@shikijs/vscode-textmate" "^9.3.0"
"@shikijs/types@1.22.2":
version "1.22.2"
resolved "https://registry.yarnpkg.com/@shikijs/types/-/types-1.22.2.tgz#695a283f19963fe0638fc2646862ba5cfc4623a8"
integrity sha512-NCWDa6LGZqTuzjsGfXOBWfjS/fDIbDdmVDug+7ykVe1IKT4c1gakrvlfFYp5NhAXH/lyqLM8wsAPo5wNy73Feg==
dependencies:
"@shikijs/vscode-textmate" "^9.3.0"
"@types/hast" "^3.0.4"
"@shikijs/vscode-textmate@^9.3.0":
version "9.3.0"
resolved "https://registry.yarnpkg.com/@shikijs/vscode-textmate/-/vscode-textmate-9.3.0.tgz#b2f1776e488c1d6c2b6cd129bab62f71bbc9c7ab"
integrity sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==
"@swc/counter@^0.1.3": "@swc/counter@^0.1.3":
version "0.1.3" version "0.1.3"
resolved "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz" resolved "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz"
@ -2112,7 +2154,7 @@
dependencies: dependencies:
"@types/unist" "^2" "@types/unist" "^2"
"@types/hast@^3.0.0": "@types/hast@^3.0.0", "@types/hast@^3.0.4":
version "3.0.4" version "3.0.4"
resolved "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz" resolved "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz"
integrity sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ== integrity sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==
@ -4430,6 +4472,23 @@ hast-util-to-html@^8.0.0:
stringify-entities "^4.0.0" stringify-entities "^4.0.0"
zwitch "^2.0.4" zwitch "^2.0.4"
hast-util-to-html@^9.0.3:
version "9.0.3"
resolved "https://registry.yarnpkg.com/hast-util-to-html/-/hast-util-to-html-9.0.3.tgz#a9999a0ba6b4919576a9105129fead85d37f302b"
integrity sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==
dependencies:
"@types/hast" "^3.0.0"
"@types/unist" "^3.0.0"
ccount "^2.0.0"
comma-separated-tokens "^2.0.0"
hast-util-whitespace "^3.0.0"
html-void-elements "^3.0.0"
mdast-util-to-hast "^13.0.0"
property-information "^6.0.0"
space-separated-tokens "^2.0.0"
stringify-entities "^4.0.0"
zwitch "^2.0.4"
hast-util-to-jsx-runtime@^2.0.0: hast-util-to-jsx-runtime@^2.0.0:
version "2.3.0" version "2.3.0"
resolved "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.0.tgz" resolved "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.0.tgz"
@ -4503,6 +4562,11 @@ html-void-elements@^2.0.0:
resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-2.0.1.tgz#29459b8b05c200b6c5ee98743c41b979d577549f" resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-2.0.1.tgz#29459b8b05c200b6c5ee98743c41b979d577549f"
integrity sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A== integrity sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==
html-void-elements@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-3.0.0.tgz#fc9dbd84af9e747249034d4d62602def6517f1d7"
integrity sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==
htmlparser2@9.1.0, htmlparser2@^9.1.0: htmlparser2@9.1.0, htmlparser2@^9.1.0:
version "9.1.0" version "9.1.0"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-9.1.0.tgz#cdb498d8a75a51f739b61d3f718136c369bc8c23" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-9.1.0.tgz#cdb498d8a75a51f739b61d3f718136c369bc8c23"
@ -6442,6 +6506,13 @@ onetime@^6.0.0:
dependencies: dependencies:
mimic-fn "^4.0.0" mimic-fn "^4.0.0"
oniguruma-to-js@0.4.3:
version "0.4.3"
resolved "https://registry.yarnpkg.com/oniguruma-to-js/-/oniguruma-to-js-0.4.3.tgz#8d899714c21f5c7d59a3c0008ca50e848086d740"
integrity sha512-X0jWUcAlxORhOqqBREgPMgnshB7ZGYszBNspP+tS9hPD3l13CdaXcHbgImoHUHlrvGx/7AvFEkTRhAGYh+jzjQ==
dependencies:
regex "^4.3.2"
oo-ascii-tree@^1.84.0: oo-ascii-tree@^1.84.0:
version "1.102.0" version "1.102.0"
resolved "https://registry.yarnpkg.com/oo-ascii-tree/-/oo-ascii-tree-1.102.0.tgz#438e67730bc8503ae28e40a5273075e5f489b875" resolved "https://registry.yarnpkg.com/oo-ascii-tree/-/oo-ascii-tree-1.102.0.tgz#438e67730bc8503ae28e40a5273075e5f489b875"
@ -6957,6 +7028,11 @@ regenerator-runtime@^0.14.0:
resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz" resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz"
integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==
regex@^4.3.2:
version "4.4.0"
resolved "https://registry.yarnpkg.com/regex/-/regex-4.4.0.tgz#cb731e2819f230fad69089e1bd854fef7569e90a"
integrity sha512-uCUSuobNVeqUupowbdZub6ggI5/JZkYyJdDogddJr60L764oxC2pMZov1fQ3wM9bdyzUILDG+Sqx6NAKAz9rKQ==
regexp.prototype.flags@^1.5.2: regexp.prototype.flags@^1.5.2:
version "1.5.2" version "1.5.2"
resolved "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz" resolved "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz"
@ -7238,6 +7314,18 @@ shebang-regex@^3.0.0:
resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz"
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
shiki@^1.22.2:
version "1.22.2"
resolved "https://registry.yarnpkg.com/shiki/-/shiki-1.22.2.tgz#ed109a3d0850504ad5a1edf8496470a2121c5b7b"
integrity sha512-3IZau0NdGKXhH2bBlUk4w1IHNxPh6A5B2sUpyY+8utLu2j/h1QpFkAaUA1bAMxOWWGtTWcAh531vnS4NJKS/lA==
dependencies:
"@shikijs/core" "1.22.2"
"@shikijs/engine-javascript" "1.22.2"
"@shikijs/engine-oniguruma" "1.22.2"
"@shikijs/types" "1.22.2"
"@shikijs/vscode-textmate" "^9.3.0"
"@types/hast" "^3.0.4"
side-channel@^1.0.4, side-channel@^1.0.6: side-channel@^1.0.4, side-channel@^1.0.6:
version "1.0.6" version "1.0.6"
resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz" resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz"