mirror of
https://github.com/DeveloLongScript/MHSF.git
synced 2026-05-09 10:54:59 -05:00
Compare commits
32 Commits
e2a9e19620
...
f5525fa30b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f5525fa30b | ||
|
|
fa7e1b1278 | ||
|
|
e51a2ecd16 | ||
|
|
00f8a1f33e | ||
|
|
13489a4145 | ||
|
|
185bd77d5f | ||
|
|
48c038df0f | ||
|
|
49c0a599a4 | ||
|
|
7caf2c1b4e | ||
|
|
c19f56b685 | ||
|
|
f1fa1d98c1 | ||
|
|
51b3050528 | ||
|
|
2589552592 | ||
|
|
742a95a9db | ||
|
|
9b5d149b35 | ||
|
|
1b1a9152c5 | ||
|
|
4150d86ec7 | ||
|
|
67bdca8516 | ||
|
|
9afc39f4d6 | ||
|
|
ceedade382 | ||
|
|
0eef4ed4f6 | ||
|
|
a319f53381 | ||
|
|
9b6c1f07f9 | ||
|
|
f665cf0373 | ||
|
|
003ee16668 | ||
|
|
df959f063e | ||
|
|
4f60dde126 | ||
|
|
2dda77e9ee | ||
|
|
00652cc4fb | ||
|
|
e9b448658a | ||
|
|
7fe52d6c47 | ||
|
|
9765548277 |
2
.vercelignore
Normal file
2
.vercelignore
Normal file
@ -0,0 +1,2 @@
|
||||
backend-mh-api/
|
||||
cron/
|
||||
3
backend-mh-api/.gitignore
vendored
Normal file
3
backend-mh-api/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
dist/
|
||||
node_modules/
|
||||
.env
|
||||
17
backend-mh-api/README.md
Normal file
17
backend-mh-api/README.md
Normal file
@ -0,0 +1,17 @@
|
||||
# MHSF Backend API
|
||||
|
||||
This has only one function, which is to get the server list from Minehut's API, but locally so it doesn't get blocked by Cloudflare.
|
||||
|
||||
To set it up, there is only one API key:
|
||||
```dotenv
|
||||
# Make a secret token to put in here
|
||||
MHSF_SECRET="..."
|
||||
```
|
||||
And make sure its also set up in the Next.js server:
|
||||
```dotenv
|
||||
# MHSF Backend API
|
||||
MHSF_BACKEND_API_LOCATION="http://..."
|
||||
MHSF_BACKEND_SECRET="..."
|
||||
```
|
||||
|
||||
You shouldn't ever really need this unless your server is blocked by Cloudflare.
|
||||
16
backend-mh-api/package.json
Normal file
16
backend-mh-api/package.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "backend-mh-api",
|
||||
"version": "1.0.0",
|
||||
"main": "dist/index.js",
|
||||
"author": "DeveloLongScript",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/express": "^5.0.0",
|
||||
"dotenv": "^16.4.7",
|
||||
"express": "^4.21.2",
|
||||
"typescript": "^5.7.2"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npx tsc -p ./tsconfig.json"
|
||||
}
|
||||
}
|
||||
27
backend-mh-api/src/index.ts
Normal file
27
backend-mh-api/src/index.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import * as express from "express";
|
||||
import { config } from "dotenv";
|
||||
|
||||
config();
|
||||
const app = express();
|
||||
|
||||
app.get("/", (req, res) => {
|
||||
res.send({ status: "up" });
|
||||
});
|
||||
|
||||
app.get("/servers", (req, res) => {
|
||||
if (
|
||||
req.headers.Authentication !==
|
||||
`MHSF-Backend-Server ${process.env.MHSF_SECRET}`
|
||||
)
|
||||
res.status(401).send({ error: "Unauthorized" });
|
||||
else
|
||||
fetch("https://api.minehut.com/servers").then((c) => {
|
||||
c.json().then((v) => {
|
||||
res.send(v);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
app.listen(6080, () => {
|
||||
console.log("Backend API listening on port 6080");
|
||||
});
|
||||
12
backend-mh-api/tsconfig.json
Normal file
12
backend-mh-api/tsconfig.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"noImplicitAny": false,
|
||||
"noEmitOnError": true,
|
||||
"removeComments": false,
|
||||
"sourceMap": true,
|
||||
"moduleResolution": "Node",
|
||||
"target": "es6",
|
||||
"outDir": "dist"
|
||||
},
|
||||
"include": ["src/**/*"]
|
||||
}
|
||||
594
backend-mh-api/yarn.lock
Normal file
594
backend-mh-api/yarn.lock
Normal file
@ -0,0 +1,594 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@types/body-parser@*":
|
||||
version "1.19.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.5.tgz#04ce9a3b677dc8bd681a17da1ab9835dc9d3ede4"
|
||||
integrity sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==
|
||||
dependencies:
|
||||
"@types/connect" "*"
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/connect@*":
|
||||
version "3.4.38"
|
||||
resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858"
|
||||
integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/express-serve-static-core@^5.0.0":
|
||||
version "5.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-5.0.3.tgz#04174d3f0836863467b7fbcbbbcd69441d205715"
|
||||
integrity sha512-JEhMNwUJt7bw728CydvYzntD0XJeTmDnvwLlbfbAhE7Tbslm/ax6bdIiUwTgeVlZTsJQPwZwKpAkyDtIjsvx3g==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
"@types/qs" "*"
|
||||
"@types/range-parser" "*"
|
||||
"@types/send" "*"
|
||||
|
||||
"@types/express@^5.0.0":
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/express/-/express-5.0.0.tgz#13a7d1f75295e90d19ed6e74cab3678488eaa96c"
|
||||
integrity sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==
|
||||
dependencies:
|
||||
"@types/body-parser" "*"
|
||||
"@types/express-serve-static-core" "^5.0.0"
|
||||
"@types/qs" "*"
|
||||
"@types/serve-static" "*"
|
||||
|
||||
"@types/http-errors@*":
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f"
|
||||
integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==
|
||||
|
||||
"@types/mime@^1":
|
||||
version "1.3.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690"
|
||||
integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==
|
||||
|
||||
"@types/node@*":
|
||||
version "22.10.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.5.tgz#95af89a3fb74a2bb41ef9927f206e6472026e48b"
|
||||
integrity sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==
|
||||
dependencies:
|
||||
undici-types "~6.20.0"
|
||||
|
||||
"@types/qs@*":
|
||||
version "6.9.17"
|
||||
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.17.tgz#fc560f60946d0aeff2f914eb41679659d3310e1a"
|
||||
integrity sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==
|
||||
|
||||
"@types/range-parser@*":
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb"
|
||||
integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==
|
||||
|
||||
"@types/send@*":
|
||||
version "0.17.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a"
|
||||
integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==
|
||||
dependencies:
|
||||
"@types/mime" "^1"
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/serve-static@*":
|
||||
version "1.15.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.7.tgz#22174bbd74fb97fe303109738e9b5c2f3064f714"
|
||||
integrity sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==
|
||||
dependencies:
|
||||
"@types/http-errors" "*"
|
||||
"@types/node" "*"
|
||||
"@types/send" "*"
|
||||
|
||||
accepts@~1.3.8:
|
||||
version "1.3.8"
|
||||
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
|
||||
integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==
|
||||
dependencies:
|
||||
mime-types "~2.1.34"
|
||||
negotiator "0.6.3"
|
||||
|
||||
array-flatten@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
|
||||
integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==
|
||||
|
||||
body-parser@1.20.3:
|
||||
version "1.20.3"
|
||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6"
|
||||
integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==
|
||||
dependencies:
|
||||
bytes "3.1.2"
|
||||
content-type "~1.0.5"
|
||||
debug "2.6.9"
|
||||
depd "2.0.0"
|
||||
destroy "1.2.0"
|
||||
http-errors "2.0.0"
|
||||
iconv-lite "0.4.24"
|
||||
on-finished "2.4.1"
|
||||
qs "6.13.0"
|
||||
raw-body "2.5.2"
|
||||
type-is "~1.6.18"
|
||||
unpipe "1.0.0"
|
||||
|
||||
bytes@3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
|
||||
integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==
|
||||
|
||||
call-bind-apply-helpers@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz#32e5892e6361b29b0b545ba6f7763378daca2840"
|
||||
integrity sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==
|
||||
dependencies:
|
||||
es-errors "^1.3.0"
|
||||
function-bind "^1.1.2"
|
||||
|
||||
call-bound@^1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.3.tgz#41cfd032b593e39176a71533ab4f384aa04fd681"
|
||||
integrity sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==
|
||||
dependencies:
|
||||
call-bind-apply-helpers "^1.0.1"
|
||||
get-intrinsic "^1.2.6"
|
||||
|
||||
content-disposition@0.5.4:
|
||||
version "0.5.4"
|
||||
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe"
|
||||
integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==
|
||||
dependencies:
|
||||
safe-buffer "5.2.1"
|
||||
|
||||
content-type@~1.0.4, content-type@~1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918"
|
||||
integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==
|
||||
|
||||
cookie-signature@1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
|
||||
integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==
|
||||
|
||||
cookie@0.7.1:
|
||||
version "0.7.1"
|
||||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.1.tgz#2f73c42142d5d5cf71310a74fc4ae61670e5dbc9"
|
||||
integrity sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==
|
||||
|
||||
debug@2.6.9:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
depd@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
|
||||
integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
|
||||
|
||||
destroy@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
|
||||
integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
|
||||
|
||||
dotenv@^16.4.7:
|
||||
version "16.4.7"
|
||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.7.tgz#0e20c5b82950140aa99be360a8a5f52335f53c26"
|
||||
integrity sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==
|
||||
|
||||
dunder-proto@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a"
|
||||
integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==
|
||||
dependencies:
|
||||
call-bind-apply-helpers "^1.0.1"
|
||||
es-errors "^1.3.0"
|
||||
gopd "^1.2.0"
|
||||
|
||||
ee-first@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
|
||||
integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
|
||||
|
||||
encodeurl@~1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
||||
integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==
|
||||
|
||||
encodeurl@~2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58"
|
||||
integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==
|
||||
|
||||
es-define-property@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa"
|
||||
integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==
|
||||
|
||||
es-errors@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f"
|
||||
integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
|
||||
|
||||
es-object-atoms@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941"
|
||||
integrity sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==
|
||||
dependencies:
|
||||
es-errors "^1.3.0"
|
||||
|
||||
escape-html@~1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
|
||||
integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==
|
||||
|
||||
etag@~1.8.1:
|
||||
version "1.8.1"
|
||||
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
||||
integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
|
||||
|
||||
express@^4.21.2:
|
||||
version "4.21.2"
|
||||
resolved "https://registry.yarnpkg.com/express/-/express-4.21.2.tgz#cf250e48362174ead6cea4a566abef0162c1ec32"
|
||||
integrity sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==
|
||||
dependencies:
|
||||
accepts "~1.3.8"
|
||||
array-flatten "1.1.1"
|
||||
body-parser "1.20.3"
|
||||
content-disposition "0.5.4"
|
||||
content-type "~1.0.4"
|
||||
cookie "0.7.1"
|
||||
cookie-signature "1.0.6"
|
||||
debug "2.6.9"
|
||||
depd "2.0.0"
|
||||
encodeurl "~2.0.0"
|
||||
escape-html "~1.0.3"
|
||||
etag "~1.8.1"
|
||||
finalhandler "1.3.1"
|
||||
fresh "0.5.2"
|
||||
http-errors "2.0.0"
|
||||
merge-descriptors "1.0.3"
|
||||
methods "~1.1.2"
|
||||
on-finished "2.4.1"
|
||||
parseurl "~1.3.3"
|
||||
path-to-regexp "0.1.12"
|
||||
proxy-addr "~2.0.7"
|
||||
qs "6.13.0"
|
||||
range-parser "~1.2.1"
|
||||
safe-buffer "5.2.1"
|
||||
send "0.19.0"
|
||||
serve-static "1.16.2"
|
||||
setprototypeof "1.2.0"
|
||||
statuses "2.0.1"
|
||||
type-is "~1.6.18"
|
||||
utils-merge "1.0.1"
|
||||
vary "~1.1.2"
|
||||
|
||||
finalhandler@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.3.1.tgz#0c575f1d1d324ddd1da35ad7ece3df7d19088019"
|
||||
integrity sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==
|
||||
dependencies:
|
||||
debug "2.6.9"
|
||||
encodeurl "~2.0.0"
|
||||
escape-html "~1.0.3"
|
||||
on-finished "2.4.1"
|
||||
parseurl "~1.3.3"
|
||||
statuses "2.0.1"
|
||||
unpipe "~1.0.0"
|
||||
|
||||
forwarded@0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
|
||||
integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==
|
||||
|
||||
fresh@0.5.2:
|
||||
version "0.5.2"
|
||||
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
|
||||
integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==
|
||||
|
||||
function-bind@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
|
||||
integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
|
||||
|
||||
get-intrinsic@^1.2.5, get-intrinsic@^1.2.6:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.7.tgz#dcfcb33d3272e15f445d15124bc0a216189b9044"
|
||||
integrity sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==
|
||||
dependencies:
|
||||
call-bind-apply-helpers "^1.0.1"
|
||||
es-define-property "^1.0.1"
|
||||
es-errors "^1.3.0"
|
||||
es-object-atoms "^1.0.0"
|
||||
function-bind "^1.1.2"
|
||||
get-proto "^1.0.0"
|
||||
gopd "^1.2.0"
|
||||
has-symbols "^1.1.0"
|
||||
hasown "^2.0.2"
|
||||
math-intrinsics "^1.1.0"
|
||||
|
||||
get-proto@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1"
|
||||
integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==
|
||||
dependencies:
|
||||
dunder-proto "^1.0.1"
|
||||
es-object-atoms "^1.0.0"
|
||||
|
||||
gopd@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1"
|
||||
integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==
|
||||
|
||||
has-symbols@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338"
|
||||
integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==
|
||||
|
||||
hasown@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
|
||||
integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
|
||||
dependencies:
|
||||
function-bind "^1.1.2"
|
||||
|
||||
http-errors@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3"
|
||||
integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==
|
||||
dependencies:
|
||||
depd "2.0.0"
|
||||
inherits "2.0.4"
|
||||
setprototypeof "1.2.0"
|
||||
statuses "2.0.1"
|
||||
toidentifier "1.0.1"
|
||||
|
||||
iconv-lite@0.4.24:
|
||||
version "0.4.24"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
||||
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
|
||||
dependencies:
|
||||
safer-buffer ">= 2.1.2 < 3"
|
||||
|
||||
inherits@2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
version "1.9.1"
|
||||
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
|
||||
integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
|
||||
|
||||
math-intrinsics@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9"
|
||||
integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==
|
||||
|
||||
media-typer@0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
|
||||
integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==
|
||||
|
||||
merge-descriptors@1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5"
|
||||
integrity sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==
|
||||
|
||||
methods@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
|
||||
integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==
|
||||
|
||||
mime-db@1.52.0:
|
||||
version "1.52.0"
|
||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
|
||||
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
|
||||
|
||||
mime-types@~2.1.24, mime-types@~2.1.34:
|
||||
version "2.1.35"
|
||||
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
|
||||
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
|
||||
dependencies:
|
||||
mime-db "1.52.0"
|
||||
|
||||
mime@1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
|
||||
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
|
||||
|
||||
ms@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||
integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==
|
||||
|
||||
ms@2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||
|
||||
negotiator@0.6.3:
|
||||
version "0.6.3"
|
||||
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
|
||||
integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==
|
||||
|
||||
object-inspect@^1.13.3:
|
||||
version "1.13.3"
|
||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.3.tgz#f14c183de51130243d6d18ae149375ff50ea488a"
|
||||
integrity sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==
|
||||
|
||||
on-finished@2.4.1:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
|
||||
integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==
|
||||
dependencies:
|
||||
ee-first "1.1.1"
|
||||
|
||||
parseurl@~1.3.3:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
|
||||
integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
|
||||
|
||||
path-to-regexp@0.1.12:
|
||||
version "0.1.12"
|
||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.12.tgz#d5e1a12e478a976d432ef3c58d534b9923164bb7"
|
||||
integrity sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==
|
||||
|
||||
proxy-addr@~2.0.7:
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025"
|
||||
integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==
|
||||
dependencies:
|
||||
forwarded "0.2.0"
|
||||
ipaddr.js "1.9.1"
|
||||
|
||||
qs@6.13.0:
|
||||
version "6.13.0"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906"
|
||||
integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==
|
||||
dependencies:
|
||||
side-channel "^1.0.6"
|
||||
|
||||
range-parser@~1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
|
||||
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
|
||||
|
||||
raw-body@2.5.2:
|
||||
version "2.5.2"
|
||||
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a"
|
||||
integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==
|
||||
dependencies:
|
||||
bytes "3.1.2"
|
||||
http-errors "2.0.0"
|
||||
iconv-lite "0.4.24"
|
||||
unpipe "1.0.0"
|
||||
|
||||
safe-buffer@5.2.1:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||
|
||||
"safer-buffer@>= 2.1.2 < 3":
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||
|
||||
send@0.19.0:
|
||||
version "0.19.0"
|
||||
resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8"
|
||||
integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==
|
||||
dependencies:
|
||||
debug "2.6.9"
|
||||
depd "2.0.0"
|
||||
destroy "1.2.0"
|
||||
encodeurl "~1.0.2"
|
||||
escape-html "~1.0.3"
|
||||
etag "~1.8.1"
|
||||
fresh "0.5.2"
|
||||
http-errors "2.0.0"
|
||||
mime "1.6.0"
|
||||
ms "2.1.3"
|
||||
on-finished "2.4.1"
|
||||
range-parser "~1.2.1"
|
||||
statuses "2.0.1"
|
||||
|
||||
serve-static@1.16.2:
|
||||
version "1.16.2"
|
||||
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296"
|
||||
integrity sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==
|
||||
dependencies:
|
||||
encodeurl "~2.0.0"
|
||||
escape-html "~1.0.3"
|
||||
parseurl "~1.3.3"
|
||||
send "0.19.0"
|
||||
|
||||
setprototypeof@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
|
||||
integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
|
||||
|
||||
side-channel-list@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad"
|
||||
integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==
|
||||
dependencies:
|
||||
es-errors "^1.3.0"
|
||||
object-inspect "^1.13.3"
|
||||
|
||||
side-channel-map@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42"
|
||||
integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==
|
||||
dependencies:
|
||||
call-bound "^1.0.2"
|
||||
es-errors "^1.3.0"
|
||||
get-intrinsic "^1.2.5"
|
||||
object-inspect "^1.13.3"
|
||||
|
||||
side-channel-weakmap@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea"
|
||||
integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==
|
||||
dependencies:
|
||||
call-bound "^1.0.2"
|
||||
es-errors "^1.3.0"
|
||||
get-intrinsic "^1.2.5"
|
||||
object-inspect "^1.13.3"
|
||||
side-channel-map "^1.0.1"
|
||||
|
||||
side-channel@^1.0.6:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9"
|
||||
integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==
|
||||
dependencies:
|
||||
es-errors "^1.3.0"
|
||||
object-inspect "^1.13.3"
|
||||
side-channel-list "^1.0.0"
|
||||
side-channel-map "^1.0.1"
|
||||
side-channel-weakmap "^1.0.2"
|
||||
|
||||
statuses@2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
|
||||
integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
|
||||
|
||||
toidentifier@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
|
||||
integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
|
||||
|
||||
type-is@~1.6.18:
|
||||
version "1.6.18"
|
||||
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
|
||||
integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
|
||||
dependencies:
|
||||
media-typer "0.3.0"
|
||||
mime-types "~2.1.24"
|
||||
|
||||
typescript@^5.7.2:
|
||||
version "5.7.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.2.tgz#3169cf8c4c8a828cde53ba9ecb3d2b1d5dd67be6"
|
||||
integrity sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==
|
||||
|
||||
undici-types@~6.20.0:
|
||||
version "6.20.0"
|
||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433"
|
||||
integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==
|
||||
|
||||
unpipe@1.0.0, unpipe@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
|
||||
integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==
|
||||
|
||||
utils-merge@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
|
||||
integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==
|
||||
|
||||
vary@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
||||
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
|
||||
5
next-sitemap.config.js
Normal file
5
next-sitemap.config.js
Normal file
@ -0,0 +1,5 @@
|
||||
/** @type {import('next-sitemap').IConfig} */
|
||||
module.exports = {
|
||||
siteUrl: "https://mhsf.app",
|
||||
generateRobotsTxt: true
|
||||
}
|
||||
@ -48,6 +48,7 @@
|
||||
"next": "14.2.10",
|
||||
"next-contentlayer": "^0.3.4",
|
||||
"next-css-obfuscator": "^2.2.16",
|
||||
"next-sitemap": "^4.2.3",
|
||||
"next-themes": "^0.4.3",
|
||||
"nextjs-toploader": "^1.6.12",
|
||||
"nprogress": "^0.2.0",
|
||||
|
||||
@ -40,7 +40,7 @@ export default function RootLayout({
|
||||
const pathname = usePathname();
|
||||
|
||||
return (
|
||||
<span className="pt-[48px]">
|
||||
<span className="pt-[48px] ">
|
||||
<Sidebar curPage={pathname as string}>{children}</Sidebar>
|
||||
</span>
|
||||
);
|
||||
|
||||
@ -85,7 +85,7 @@ export default function Settings() {
|
||||
<br />
|
||||
<strong className="font-bold">Unlink Account</strong>
|
||||
<div className="flex items-center">
|
||||
<p>Unlink your Minecraft acconut if you have already linked one.</p>
|
||||
<p>Unlink your Minecraft account if you have already linked one.</p>
|
||||
|
||||
{!linked && (
|
||||
<Button className="h-[30px] ml-2" disabled>
|
||||
|
||||
@ -43,6 +43,7 @@ import type { Metadata, Viewport } from "next";
|
||||
import { Inter as interFont } from "next/font/google";
|
||||
import LayoutPart from "@/components/feat/LayoutPart";
|
||||
import AllBanners from "@/components/feat/AllBanners";
|
||||
import Footer from "@/components/misc/Footer";
|
||||
|
||||
export const extraMetadata = {
|
||||
twitter: {
|
||||
@ -84,6 +85,7 @@ export default async function RootLayout({
|
||||
<Analytics />
|
||||
<NewDomainDialog />
|
||||
<UnofficalDialog />
|
||||
<Footer />
|
||||
</TooltipProvider>
|
||||
</ThemeProvider>
|
||||
</ClerkThemeProvider>
|
||||
|
||||
@ -132,16 +132,18 @@ export default function ServerPage({ params }: { params: { server: string } }) {
|
||||
<ColorProvider server={params.server}>
|
||||
<div className={"pt-[300px] xl:px-[100px]"}>
|
||||
<Banner server={params.server} />
|
||||
<div className="pt-8 z-10 relative">
|
||||
<div className="pt-8 z-8 relative">
|
||||
<ServerView server={params.server} />
|
||||
</div>
|
||||
|
||||
<StickyTopbar scrollElevation={100} className="pt-4">
|
||||
<StickyTopbar scrollElevation={100} className="pt-4 z-10">
|
||||
<TabServer server={params.server} tabDef="general" />
|
||||
</StickyTopbar>
|
||||
<br />
|
||||
<div className="z-8 relative">
|
||||
<AfterServerView server={params.server} />
|
||||
</div>
|
||||
</div>
|
||||
</ColorProvider>
|
||||
</main>
|
||||
);
|
||||
|
||||
@ -118,7 +118,7 @@ export default function AfterServerView({ server }: { server: string }) {
|
||||
<QRCodeGenerator server={server} />
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
<FadeIn className="relative z-10">
|
||||
<FadeIn className="relative z-8">
|
||||
<div className="grid sm:grid-cols-6 h-full pl-4 pr-4 ">
|
||||
<div className="ml-5 mb-2 flex items-center sm:hidden overflow-auto w-[calc(100vw-5rem)]">
|
||||
{(description != "" || discord != "") && (
|
||||
|
||||
@ -29,28 +29,48 @@
|
||||
*/
|
||||
|
||||
"use client";
|
||||
|
||||
import { getCustomization } from "@/lib/api";
|
||||
import { useEffect, useState } from "react";
|
||||
import "@/themes.css";
|
||||
import { toast } from "sonner";
|
||||
import { useRouter } from "@/lib/useRouter";
|
||||
import { useEffectOnce } from "@/lib/useEffectOnce";
|
||||
|
||||
export default function ColorProvider({
|
||||
server,
|
||||
children,
|
||||
fetch,
|
||||
fetchV,
|
||||
}: {
|
||||
server: string;
|
||||
children: any;
|
||||
fetch?: any;
|
||||
fetchV?: any;
|
||||
}) {
|
||||
const [color, setColor] = useState("zinc");
|
||||
const nav = useRouter();
|
||||
|
||||
useEffectOnce(() => {
|
||||
fetch("https://api.minehut.com/server/" + server + "?byName=true")
|
||||
.then((c) => c.json())
|
||||
.then((c: any) => {
|
||||
console.log(c.server.name, server);
|
||||
if (c.server.name !== server) {
|
||||
toast.warning(
|
||||
"The capitalization of this server was incorrect. If your using a permanent link resource, please change it to account for a new name. (" +
|
||||
c.server.name +
|
||||
") Redirecting now.",
|
||||
{ duration: 15000 }
|
||||
);
|
||||
nav.replace("/server/" + c.server.name);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!fetch)
|
||||
if (!fetchV)
|
||||
getCustomization(server).then((v) =>
|
||||
setColor(v != null ? v.colorScheme : "zinc")
|
||||
);
|
||||
else setColor(fetch.colorScheme);
|
||||
else setColor(fetchV.colorScheme);
|
||||
}, []);
|
||||
|
||||
return <div className={`theme-${color}`}>{children}</div>;
|
||||
|
||||
@ -68,7 +68,6 @@ import {
|
||||
} from "@/lib/api";
|
||||
import IconDisplay from "./IconDisplay";
|
||||
import ServerSingle from "@/lib/single";
|
||||
import SnowfallController from "./misc/SnowfallController";
|
||||
import { toast } from "sonner";
|
||||
import { ServerResponse, OnlineServer } from "@/lib/types/mh-server";
|
||||
import {
|
||||
@ -856,7 +855,6 @@ export function CommandBarer() {
|
||||
<ServerCommandBar />
|
||||
<OfflineServerCB />
|
||||
<RandomServerDialog />
|
||||
<SnowfallController />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ export function Sidebar({
|
||||
return (
|
||||
<ResizablePanelGroup
|
||||
direction="horizontal"
|
||||
className="min-h-[calc(100vh-70px)] pt-[70px]"
|
||||
className="min-h-[calc(100vh-70px)] pt-[70px] xl:px-[100px] "
|
||||
>
|
||||
<ResizablePanel className="max-md:hidden min-w-[285px] max-w-[285px] w-[285px]">
|
||||
<div className="w-[300px] ml-[10px]">
|
||||
|
||||
@ -49,7 +49,13 @@ import {
|
||||
} from "./ui/card";
|
||||
import { TooltipContent, TooltipTrigger } from "./ui/tooltip";
|
||||
|
||||
export default function ServerCard({ b, motd, mini, favs }: any) {
|
||||
export default function ServerCard({
|
||||
b,
|
||||
motd,
|
||||
mini,
|
||||
favs,
|
||||
selectedProperties,
|
||||
}: any) {
|
||||
const router = useRouter();
|
||||
const clipboard = useClipboard();
|
||||
const [favoriteStar, setFavoriteStar] = useState(false);
|
||||
@ -165,17 +171,21 @@ export default function ServerCard({ b, motd, mini, favs }: any) {
|
||||
</DrawerFooter>
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
{b.author != undefined ? (
|
||||
|
||||
{selectedProperties.includes("Author") &&
|
||||
b.author != undefined ? (
|
||||
<div className="text-sm text-muted-foreground font-normal tracking-normal">
|
||||
by {b.author}
|
||||
</div>
|
||||
) : (
|
||||
<br />
|
||||
)}
|
||||
<TagShower server={b} />
|
||||
{selectedProperties.includes("Tags") && <TagShower server={b} />}
|
||||
</CardTitle>
|
||||
<CardDescription className="float-left inline ">
|
||||
<span className="flex items-center">
|
||||
{selectedProperties.includes("Players Online") && (
|
||||
<>
|
||||
{b.playerData.playerCount == 0 ? (
|
||||
<div
|
||||
className="items-center border"
|
||||
@ -196,14 +206,19 @@ export default function ServerCard({ b, motd, mini, favs }: any) {
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
{selectedProperties.includes("Players Online") && (
|
||||
<span className="pl-1">
|
||||
{b.playerData.playerCount}{" "}
|
||||
{b.playerData.playerCount == 1 ? "player" : "players"}{" "}
|
||||
currently online {favs && <>• {favs} favorited</>}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
|
||||
{selectedProperties.includes("Actions") && (
|
||||
<ContextMenu>
|
||||
<ContextMenuTrigger>
|
||||
<>
|
||||
@ -256,9 +271,10 @@ export default function ServerCard({ b, motd, mini, favs }: any) {
|
||||
</Link>
|
||||
</ContextMenuContent>
|
||||
</ContextMenu>
|
||||
)}
|
||||
</CardDescription>
|
||||
<CardContent>
|
||||
{motd && (
|
||||
<CardContent className="p-0">
|
||||
{motd && selectedProperties.includes("MOTD") && (
|
||||
<span
|
||||
dangerouslySetInnerHTML={{ __html: motd }}
|
||||
className="w-[30px] text-center break-all overflow-hidden"
|
||||
|
||||
@ -140,7 +140,7 @@ export default function ServerCustomize({
|
||||
});
|
||||
});
|
||||
});
|
||||
}, [isSignedIn]);
|
||||
}, [isSignedIn, server]);
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
|
||||
@ -44,34 +44,16 @@ import {
|
||||
AllCommunityModule,
|
||||
ModuleRegistry,
|
||||
colorSchemeDarkBlue,
|
||||
colorSchemeDarkWarm,
|
||||
colorSchemeLightCold,
|
||||
colorSchemeLightWarm,
|
||||
themeQuartz,
|
||||
} from "ag-grid-community";
|
||||
import {
|
||||
Menubar,
|
||||
MenubarCheckboxItem,
|
||||
MenubarContent,
|
||||
MenubarItem,
|
||||
MenubarMenu,
|
||||
MenubarRadioGroup,
|
||||
MenubarRadioItem,
|
||||
MenubarSeparator,
|
||||
MenubarShortcut,
|
||||
MenubarSub,
|
||||
MenubarSubContent,
|
||||
MenubarSubTrigger,
|
||||
MenubarTrigger,
|
||||
} from "@/components/ui/menubar";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
import { allCategories, allTags } from "@/config/tags";
|
||||
import events from "@/lib/commandEvent";
|
||||
import { allTags } from "@/config/tags";
|
||||
import ServersList from "@/lib/list";
|
||||
import { OnlineServer } from "@/lib/types/mh-server";
|
||||
import useClipboard from "@/lib/useClipboard";
|
||||
@ -81,6 +63,7 @@ import { cn } from "@/lib/utils";
|
||||
import { SignedIn, SignedOut, useUser } from "@clerk/nextjs";
|
||||
import { ChatBubbleIcon, InputIcon } from "@radix-ui/react-icons";
|
||||
import {
|
||||
ArrowDown,
|
||||
ArrowDownZA,
|
||||
Check,
|
||||
CircleUser,
|
||||
@ -93,7 +76,6 @@ import {
|
||||
Sun,
|
||||
XIcon,
|
||||
} from "lucide-react";
|
||||
import { CommandIcon } from "lucide-react";
|
||||
import { useTheme } from "next-themes";
|
||||
import Link from "next/link";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
@ -112,12 +94,13 @@ import { pageFind } from "./misc/Link";
|
||||
import { Badge } from "./ui/badge";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "./ui/popover";
|
||||
import { Skeleton } from "./ui/skeleton";
|
||||
import { affiliates } from "@/config/affiliates";
|
||||
import { LoadingSpinner } from "./ui/loading-spinner";
|
||||
import StickyTopbar from "./misc/StickyTopbar";
|
||||
import { HoverCard } from "@radix-ui/react-hover-card";
|
||||
import { HoverCardTrigger } from "./ui/hover-card";
|
||||
import { ExampleChart } from "./charts/ExampleChart";
|
||||
import ServerListInterface from "./misc/ServerListInterface";
|
||||
import NoItems from "./misc/NoItems";
|
||||
|
||||
// ag-grid
|
||||
ModuleRegistry.registerModules([AllCommunityModule]);
|
||||
@ -184,16 +167,23 @@ export default function ServerList() {
|
||||
const router = useRouter();
|
||||
const { user, isSignedIn } = useUser();
|
||||
const [pOS, setpOS] = useState(false);
|
||||
const [selectedProperties, setSelectedProperties] = useState<string[]>([
|
||||
"Author",
|
||||
"MOTD",
|
||||
"Tags",
|
||||
"Players Online",
|
||||
"Actions",
|
||||
]);
|
||||
const [ipr, setIPR] = useState<string>("4");
|
||||
const [presentationMode, setPresentationMode] = useState<"table" | "grid">(
|
||||
"grid",
|
||||
"grid"
|
||||
);
|
||||
const [am, setAM] = useState(false);
|
||||
const [filters, setFilters] = useState<
|
||||
Array<(server: OnlineServer) => Promise<boolean>>
|
||||
>([]);
|
||||
const [randomData, setRandomData] = useState<OnlineServer | undefined>(
|
||||
undefined,
|
||||
undefined
|
||||
);
|
||||
const { resolvedTheme } = useTheme();
|
||||
const [color, setColor] = useState("#ffffff");
|
||||
@ -375,7 +365,7 @@ export default function ServerList() {
|
||||
className={cn(
|
||||
"relative w-64 cursor-pointer overflow-hidden rounded-xl border no-underline " +
|
||||
"border-gray-950/[.1] bg-gray-950/[.01] hover:bg-gray-950/[.05] " +
|
||||
"dark:border-gray-50/[.1] dark:bg-gray-50/[.10] dark:hover:bg-gray-50/[.15]",
|
||||
"dark:border-gray-50/[.1] dark:bg-gray-50/[.10] dark:hover:bg-gray-50/[.15]"
|
||||
)}
|
||||
onClick={() =>
|
||||
router.push(pageFind(`Server:${server.name}`))
|
||||
@ -409,7 +399,7 @@ export default function ServerList() {
|
||||
className={cn(
|
||||
"relative w-64 cursor-pointer overflow-hidden rounded-xl border no-underline " +
|
||||
"border-gray-950/[.1] bg-gray-950/[.01] hover:bg-gray-950/[.05] " +
|
||||
"dark:border-gray-50/[.1] dark:bg-gray-50/[.10] dark:hover:bg-gray-50/[.15]",
|
||||
"dark:border-gray-50/[.1] dark:bg-gray-50/[.10] dark:hover:bg-gray-50/[.15]"
|
||||
)}
|
||||
onClick={() => router.push(`/server/${server.name}`)}
|
||||
>
|
||||
@ -464,10 +454,15 @@ export default function ServerList() {
|
||||
Monitor your success
|
||||
</h1>
|
||||
<p className="animate-fade-in mb-12 -translate-y-4 text-balance text-lg tracking-tight text-gray-400 opacity-0 [--animation-delay:400ms] md:text-xl">
|
||||
Ever wondered how a server was doing? MHSF constantly monitors servers
|
||||
and shows you statistics about how a server is doing at any point of time.
|
||||
Ever wondered how a server was doing? MHSF constantly monitors
|
||||
servers and shows you statistics about how a server is doing at
|
||||
any point of time.
|
||||
</p>
|
||||
<ExampleChart />
|
||||
<br className="mb-8" />
|
||||
<span className="text-sm flex items-center justify-center mt-32">
|
||||
<ArrowDown className="mr-2" size={16} /> Check it out below!
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<br />
|
||||
@ -555,30 +550,51 @@ export default function ServerList() {
|
||||
<Separator />
|
||||
<ClientFadeIn delay={100}>
|
||||
<StickyTopbar scrollElevation={250} className="p-2">
|
||||
<Menubar className="mt-3 border rounded shadow">
|
||||
<MenubarMenu>
|
||||
<MenubarTrigger>Servers</MenubarTrigger>
|
||||
<MenubarContent>
|
||||
<MenubarItem
|
||||
onSelect={() => events.emit("search-request-event")}
|
||||
>
|
||||
Search Servers
|
||||
<MenubarShortcut className="flex items-center ml-3">
|
||||
<CommandIcon size={14} />
|
||||
+Shift+K
|
||||
</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarItem
|
||||
onSelect={() => {
|
||||
<ServerListInterface
|
||||
viewProps={{
|
||||
setPresentationMode,
|
||||
presentationMode,
|
||||
selectedProperties,
|
||||
setSelectedProperties,
|
||||
hero,
|
||||
setHero,
|
||||
padding,
|
||||
paddingChangerCallback: (v: any) => {
|
||||
if (am)
|
||||
toast.warning(
|
||||
"These settings will not change over reloads because you have account specific options enabled",
|
||||
{
|
||||
action: {
|
||||
label: "Check settings",
|
||||
onClick: () =>
|
||||
router.push("/account/settings/options"),
|
||||
},
|
||||
}
|
||||
);
|
||||
setPadding(v);
|
||||
},
|
||||
am,
|
||||
iprChangerCallback: (v: any) => {
|
||||
if (am)
|
||||
toast.warning(
|
||||
"These settings will not change over reloads because you have account specific options enabled",
|
||||
{
|
||||
action: {
|
||||
label: "Check settings",
|
||||
onClick: () =>
|
||||
router.push("/account/settings/options"),
|
||||
},
|
||||
}
|
||||
);
|
||||
setIPR(v);
|
||||
},
|
||||
ipr,
|
||||
}}
|
||||
pickRandomServerCallback={() => {
|
||||
setRandomData(serverList.getRandomServer());
|
||||
setRandom(true);
|
||||
}}
|
||||
>
|
||||
Pick Random Server
|
||||
</MenubarItem>
|
||||
<MenubarSeparator />
|
||||
<MenubarItem
|
||||
onSelect={() => {
|
||||
refreshCallback={() => {
|
||||
toast.promise(
|
||||
new Promise((s, e) => {
|
||||
setLoading(true);
|
||||
@ -602,11 +618,9 @@ export default function ServerList() {
|
||||
|
||||
serverList.getMOTDs(stringList).then((c) => {
|
||||
var updatedSL = motdList;
|
||||
c.forEach(
|
||||
(b: { server: string; motd: string }) => {
|
||||
c.forEach((b: { server: string; motd: string }) => {
|
||||
updatedSL[b.server] = b.motd;
|
||||
},
|
||||
);
|
||||
});
|
||||
setMotdList(updatedSL);
|
||||
setServers(serverList.currentServers);
|
||||
setLoading(false);
|
||||
@ -618,22 +632,107 @@ export default function ServerList() {
|
||||
});
|
||||
}),
|
||||
{
|
||||
success: "Succesfully refreshed servers",
|
||||
loading: "Refreshing...",
|
||||
success: "Succesfully reloaded servers",
|
||||
loading: "Reloading...",
|
||||
error: "Error while refreshing",
|
||||
},
|
||||
}
|
||||
);
|
||||
}}
|
||||
>
|
||||
Refresh
|
||||
</MenubarItem>
|
||||
</MenubarContent>
|
||||
</MenubarMenu>
|
||||
<MenubarMenu>
|
||||
<MenubarTrigger>Filter</MenubarTrigger>
|
||||
<MenubarContent className="max-h-[400px] overflow-auto">
|
||||
<MenubarRadioGroup
|
||||
onValueChange={(v) => {
|
||||
linksProps={{
|
||||
templateFilter,
|
||||
tagChangerValueCallback: (tag: any) => {
|
||||
return nameFilters["t-" + tag.docsName];
|
||||
},
|
||||
categoryChangerValueCallback: (categorie: any) => {
|
||||
return nameFilters["c-" + categorie.name];
|
||||
},
|
||||
categoryChangerCallback: (categorie: any) => async (b: any) => {
|
||||
var filt = nameFilters;
|
||||
filt["c-" + categorie.name] = b;
|
||||
setNameFilters(filt);
|
||||
if (b) {
|
||||
var filt2 = filters;
|
||||
filt2.push(categorie.condition);
|
||||
setFilters(filt2);
|
||||
} else {
|
||||
var filt2 = filters;
|
||||
filt2.splice(filt2.indexOf(categorie.condition), 1);
|
||||
setFilters(filt2);
|
||||
}
|
||||
serverList.editFilters(filters);
|
||||
serverList.fetchDataAndFilter().then(() => {
|
||||
serverList.moveListDown();
|
||||
|
||||
let stringList: Array<{
|
||||
server: string;
|
||||
motd: string;
|
||||
}> = [];
|
||||
let obj: any = {};
|
||||
|
||||
serverList.currentServers.forEach((b) => {
|
||||
stringList.push({ motd: b.motd, server: b.name });
|
||||
});
|
||||
|
||||
serverList.getMOTDs(stringList).then((c) => {
|
||||
var updatedSL = motdList;
|
||||
c.forEach((b: { server: string; motd: string }) => {
|
||||
updatedSL[b.server] = b.motd;
|
||||
});
|
||||
setMotdList(updatedSL);
|
||||
setServers(serverList.currentServers);
|
||||
});
|
||||
});
|
||||
},
|
||||
tagChangerCallback: (tag: any) => async (b: any) => {
|
||||
var filt = nameFilters;
|
||||
filt["t-" + tag.docsName] = b;
|
||||
setNameFilters(filt);
|
||||
if (b) {
|
||||
var filt2 = filters;
|
||||
filt2.push(tag.condition);
|
||||
setFilters(filt2);
|
||||
} else {
|
||||
var filt2 = filters;
|
||||
filt2.splice(filt2.indexOf(tag.condition), 1);
|
||||
setFilters(filt2);
|
||||
}
|
||||
serverList.editFilters(filters);
|
||||
serverList.fetchDataAndFilter().then(() => {
|
||||
serverList.moveListDown();
|
||||
|
||||
let stringList: Array<{
|
||||
server: string;
|
||||
motd: string;
|
||||
}> = [];
|
||||
let obj: any = {};
|
||||
|
||||
serverList.currentServers.forEach((b) => {
|
||||
stringList.push({
|
||||
motd: b.motd,
|
||||
server: b.name,
|
||||
});
|
||||
});
|
||||
|
||||
serverList.getMOTDs(stringList).then((c) => {
|
||||
var updatedSL = motdList;
|
||||
c.forEach((b: { server: string; motd: string }) => {
|
||||
updatedSL[b.server] = b.motd;
|
||||
});
|
||||
setMotdList(updatedSL);
|
||||
setServers(serverList.currentServers);
|
||||
});
|
||||
});
|
||||
},
|
||||
serverSizeChangerValueCallback: () => {
|
||||
if (nameFilters["smaller-tf"]) {
|
||||
return "smaller";
|
||||
}
|
||||
if (nameFilters["bigger-tf"]) {
|
||||
return "bigger";
|
||||
}
|
||||
return "none";
|
||||
},
|
||||
serverSizeChangerCallback: (v: any) => {
|
||||
toast.promise(
|
||||
new Promise((g, b) => {
|
||||
if (v == "smaller") {
|
||||
@ -668,11 +767,9 @@ export default function ServerList() {
|
||||
|
||||
serverList.getMOTDs(stringList).then((c) => {
|
||||
var updatedSL = motdList;
|
||||
c.forEach(
|
||||
(b: { server: string; motd: string }) => {
|
||||
c.forEach((b: { server: string; motd: string }) => {
|
||||
updatedSL[b.server] = b.motd;
|
||||
},
|
||||
);
|
||||
});
|
||||
setMotdList(updatedSL);
|
||||
setServers(serverList.currentServers);
|
||||
g(undefined);
|
||||
@ -710,11 +807,9 @@ export default function ServerList() {
|
||||
|
||||
serverList.getMOTDs(stringList).then((c) => {
|
||||
var updatedSL = motdList;
|
||||
c.forEach(
|
||||
(b: { server: string; motd: string }) => {
|
||||
c.forEach((b: { server: string; motd: string }) => {
|
||||
updatedSL[b.server] = b.motd;
|
||||
},
|
||||
);
|
||||
});
|
||||
setMotdList(updatedSL);
|
||||
setServers(serverList.currentServers);
|
||||
g(undefined);
|
||||
@ -752,11 +847,9 @@ export default function ServerList() {
|
||||
|
||||
serverList.getMOTDs(stringList).then((c) => {
|
||||
var updatedSL = motdList;
|
||||
c.forEach(
|
||||
(b: { server: string; motd: string }) => {
|
||||
c.forEach((b: { server: string; motd: string }) => {
|
||||
updatedSL[b.server] = b.motd;
|
||||
},
|
||||
);
|
||||
});
|
||||
setMotdList(updatedSL);
|
||||
setServers(serverList.currentServers);
|
||||
g(undefined);
|
||||
@ -768,283 +861,11 @@ export default function ServerList() {
|
||||
error: "Error while changing filters",
|
||||
loading: "Changing filters...",
|
||||
success: "Changed filters!",
|
||||
},
|
||||
);
|
||||
}}
|
||||
value={(() => {
|
||||
if (nameFilters["smaller-tf"]) {
|
||||
return "smaller";
|
||||
} else if (nameFilters["bigger-tf"]) {
|
||||
return "bigger";
|
||||
} else {
|
||||
return "none";
|
||||
}
|
||||
})()}
|
||||
>
|
||||
<MenubarRadioItem value="smaller">
|
||||
<div className="block">
|
||||
Only allow smaller servers
|
||||
<br />
|
||||
<span className="text-sm text-muted-foreground">
|
||||
Only allow servers that have the player range 7-15,
|
||||
and cannot <br />
|
||||
be Always Online.
|
||||
</span>
|
||||
</div>
|
||||
</MenubarRadioItem>
|
||||
<MenubarRadioItem value="bigger">
|
||||
<div className="block">
|
||||
Only allow bigger servers
|
||||
<br />
|
||||
<span className="text-sm text-muted-foreground">
|
||||
Only allow servers with more than 15 players.
|
||||
</span>
|
||||
</div>
|
||||
</MenubarRadioItem>
|
||||
<MenubarRadioItem value="none">
|
||||
No/custom requirements
|
||||
</MenubarRadioItem>
|
||||
</MenubarRadioGroup>
|
||||
<MenubarSeparator />
|
||||
<MenubarSub>
|
||||
<span className="text-sm text-muted-foreground ml-2">
|
||||
Tags
|
||||
</span>
|
||||
</MenubarSub>
|
||||
{allTags.map((tag) => (
|
||||
<div key={tag.docsName}>
|
||||
{tag.docsName && tag.__filter == undefined && (
|
||||
<MenubarCheckboxItem
|
||||
disabled={templateFilter && tag.__disab != undefined}
|
||||
id={tag.docsName}
|
||||
checked={(() => {
|
||||
return nameFilters["t-" + tag.docsName];
|
||||
})()}
|
||||
onCheckedChange={async (b) => {
|
||||
var filt = nameFilters;
|
||||
filt["t-" + tag.docsName] = b;
|
||||
setNameFilters(filt);
|
||||
if (b) {
|
||||
var filt2 = filters;
|
||||
filt2.push(tag.condition);
|
||||
setFilters(filt2);
|
||||
} else {
|
||||
var filt2 = filters;
|
||||
filt2.splice(filt2.indexOf(tag.condition), 1);
|
||||
setFilters(filt2);
|
||||
}
|
||||
serverList.editFilters(filters);
|
||||
serverList.fetchDataAndFilter().then(() => {
|
||||
serverList.moveListDown();
|
||||
|
||||
let stringList: Array<{
|
||||
server: string;
|
||||
motd: string;
|
||||
}> = [];
|
||||
let obj: any = {};
|
||||
|
||||
serverList.currentServers.forEach((b) => {
|
||||
stringList.push({
|
||||
motd: b.motd,
|
||||
server: b.name,
|
||||
});
|
||||
});
|
||||
|
||||
serverList.getMOTDs(stringList).then((c) => {
|
||||
var updatedSL = motdList;
|
||||
c.forEach(
|
||||
(b: { server: string; motd: string }) => {
|
||||
updatedSL[b.server] = b.motd;
|
||||
},
|
||||
);
|
||||
setMotdList(updatedSL);
|
||||
setServers(serverList.currentServers);
|
||||
});
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Badge variant={tag.role} className="mr-1">
|
||||
{tag.docsName}
|
||||
</Badge>
|
||||
</MenubarCheckboxItem>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
<MenubarSeparator />
|
||||
<MenubarSub>
|
||||
<span className="text-sm text-muted-foreground ml-2">
|
||||
Categories
|
||||
</span>
|
||||
</MenubarSub>
|
||||
{allCategories.map((categorie) => (
|
||||
<MenubarCheckboxItem
|
||||
id={categorie.name}
|
||||
key={categorie.name}
|
||||
onCheckedChange={async (b) => {
|
||||
var filt = nameFilters;
|
||||
filt["c-" + categorie.name] = b;
|
||||
setNameFilters(filt);
|
||||
if (b) {
|
||||
var filt2 = filters;
|
||||
filt2.push(categorie.condition);
|
||||
setFilters(filt2);
|
||||
} else {
|
||||
var filt2 = filters;
|
||||
filt2.splice(filt2.indexOf(categorie.condition), 1);
|
||||
setFilters(filt2);
|
||||
}
|
||||
serverList.editFilters(filters);
|
||||
serverList.fetchDataAndFilter().then(() => {
|
||||
serverList.moveListDown();
|
||||
|
||||
let stringList: Array<{
|
||||
server: string;
|
||||
motd: string;
|
||||
}> = [];
|
||||
let obj: any = {};
|
||||
|
||||
serverList.currentServers.forEach((b) => {
|
||||
stringList.push({ motd: b.motd, server: b.name });
|
||||
});
|
||||
|
||||
serverList.getMOTDs(stringList).then((c) => {
|
||||
var updatedSL = motdList;
|
||||
c.forEach((b: { server: string; motd: string }) => {
|
||||
updatedSL[b.server] = b.motd;
|
||||
});
|
||||
setMotdList(updatedSL);
|
||||
setServers(serverList.currentServers);
|
||||
});
|
||||
});
|
||||
}}
|
||||
checked={(() => {
|
||||
return nameFilters["c-" + categorie.name];
|
||||
})()}
|
||||
>
|
||||
<Badge variant={categorie.role} className="mr-1">
|
||||
{categorie.name}
|
||||
</Badge>
|
||||
</MenubarCheckboxItem>
|
||||
))}
|
||||
</MenubarContent>
|
||||
</MenubarMenu>
|
||||
<MenubarMenu>
|
||||
<MenubarTrigger>View</MenubarTrigger>
|
||||
<MenubarContent>
|
||||
<MenubarSub>
|
||||
<MenubarSubTrigger>Mode</MenubarSubTrigger>
|
||||
<MenubarSubContent>
|
||||
<MenubarRadioGroup
|
||||
value={presentationMode}
|
||||
onValueChange={(v) =>
|
||||
setPresentationMode(v as "grid" | "table")
|
||||
}
|
||||
>
|
||||
<MenubarRadioItem value="grid">Grid</MenubarRadioItem>
|
||||
<MenubarRadioItem value="table">Table</MenubarRadioItem>
|
||||
</MenubarRadioGroup>
|
||||
</MenubarSubContent>
|
||||
</MenubarSub>
|
||||
<MenubarSub>
|
||||
<MenubarSubTrigger disabled={presentationMode === "table"} className={presentationMode === "table" ? "text-muted-foreground" : ""}>
|
||||
Grid
|
||||
</MenubarSubTrigger>
|
||||
<MenubarSubContent>
|
||||
<MenubarRadioGroup
|
||||
value={ipr}
|
||||
onValueChange={(v) => {
|
||||
if (am)
|
||||
toast.warning(
|
||||
"These settings will not change over reloads because you have account specific options enabled",
|
||||
{
|
||||
action: {
|
||||
label: "Check settings",
|
||||
onClick: () =>
|
||||
router.push("/account/settings/options"),
|
||||
},
|
||||
},
|
||||
);
|
||||
setIPR(v);
|
||||
}}
|
||||
>
|
||||
<MenubarRadioItem value="4">
|
||||
4 items per row
|
||||
</MenubarRadioItem>
|
||||
<MenubarRadioItem value="5">
|
||||
5 items per row
|
||||
</MenubarRadioItem>
|
||||
<MenubarRadioItem value="6">
|
||||
6 items per row
|
||||
</MenubarRadioItem>
|
||||
</MenubarRadioGroup>
|
||||
</MenubarSubContent>
|
||||
</MenubarSub>
|
||||
<MenubarSub>
|
||||
<MenubarSubTrigger>Padding</MenubarSubTrigger>
|
||||
<MenubarSubContent>
|
||||
<MenubarRadioGroup
|
||||
value={padding.toString()}
|
||||
onValueChange={(v) => {
|
||||
if (am)
|
||||
toast.warning(
|
||||
"These settings will not change over reloads because you have account specific options enabled",
|
||||
{
|
||||
action: {
|
||||
label: "Check settings",
|
||||
onClick: () =>
|
||||
router.push("/account/settings/options"),
|
||||
},
|
||||
},
|
||||
);
|
||||
setPadding(v);
|
||||
}}
|
||||
>
|
||||
<MenubarRadioItem value="0">Default</MenubarRadioItem>
|
||||
<MenubarSeparator />
|
||||
<MenubarRadioItem value="15">15px</MenubarRadioItem>
|
||||
<MenubarRadioItem value="30">30px</MenubarRadioItem>
|
||||
<MenubarRadioItem value="40">40px</MenubarRadioItem>
|
||||
<MenubarRadioItem value="60">60px</MenubarRadioItem>
|
||||
<MenubarRadioItem value="100">100px</MenubarRadioItem>
|
||||
<MenubarRadioItem value="200">200px</MenubarRadioItem>
|
||||
</MenubarRadioGroup>
|
||||
<MenubarSeparator />
|
||||
<MenubarCheckboxItem
|
||||
checked={pOS}
|
||||
onCheckedChange={setpOS}
|
||||
>
|
||||
Only use padding on servers
|
||||
</MenubarCheckboxItem>
|
||||
</MenubarSubContent>
|
||||
</MenubarSub>
|
||||
<MenubarSeparator />
|
||||
<SignedIn>
|
||||
<MenubarCheckboxItem
|
||||
checked={hero}
|
||||
onCheckedChange={setHero}
|
||||
>
|
||||
Show Hero
|
||||
</MenubarCheckboxItem>
|
||||
</SignedIn>
|
||||
<MenubarItem onClick={() => router.push("/docs")}>
|
||||
View the docs
|
||||
</MenubarItem>
|
||||
{am && (
|
||||
<MenubarItem
|
||||
onClick={() => router.push("/account/settings")}
|
||||
className="block"
|
||||
>
|
||||
Using saved settings in Preferences
|
||||
<br />
|
||||
<span className="text-muted-foreground text-xs">
|
||||
Your using settings stored on your account, that are not
|
||||
temporary.
|
||||
</span>
|
||||
</MenubarItem>
|
||||
)}
|
||||
</MenubarContent>
|
||||
</MenubarMenu>
|
||||
</Menubar>
|
||||
/>
|
||||
</StickyTopbar>
|
||||
</ClientFadeIn>
|
||||
|
||||
@ -1107,7 +928,7 @@ export default function ServerList() {
|
||||
onClick={() => {
|
||||
setTextCopied(true);
|
||||
clipboard.writeText(
|
||||
randomData.name + ".mshf.minehut.gg",
|
||||
randomData.name + ".mshf.minehut.gg"
|
||||
);
|
||||
toast.success("Copied!");
|
||||
setTimeout(() => setTextCopied(false), 1000);
|
||||
@ -1150,13 +971,9 @@ export default function ServerList() {
|
||||
}}
|
||||
loader={<LoadingSpinner className="flex items-center" />}
|
||||
endMessage={
|
||||
<p
|
||||
style={{ textAlign: "center" }}
|
||||
dangerouslySetInnerHTML={{
|
||||
__html:
|
||||
randomText + "<br /> <strong>You've seen it all</strong>",
|
||||
}}
|
||||
/>
|
||||
<p style={{ textAlign: "center" }}>
|
||||
<NoItems title="You've scrolled to the very bottom!" />
|
||||
</p>
|
||||
}
|
||||
style={{
|
||||
overflow: "hidden !important",
|
||||
@ -1219,7 +1036,11 @@ export default function ServerList() {
|
||||
))}
|
||||
</div>
|
||||
)} </> */}
|
||||
<ServerCard b={b} motd={motdList[b.name]} />
|
||||
<ServerCard
|
||||
b={b}
|
||||
motd={motdList[b.name]}
|
||||
selectedProperties={selectedProperties}
|
||||
/>
|
||||
</>
|
||||
))}
|
||||
</div>
|
||||
@ -1319,7 +1140,7 @@ export default function ServerList() {
|
||||
className="md:min-w-[128px] md:max-w-[328px] h-[32px] mt-1 ml-2"
|
||||
onClick={() => {
|
||||
clipboard.writeText(
|
||||
c.data.name + ".mshf.minehut.gg",
|
||||
c.data.name + ".mshf.minehut.gg"
|
||||
);
|
||||
toast.success("Copied IP to clipboard");
|
||||
}}
|
||||
|
||||
@ -39,7 +39,6 @@ import { CloudSnow, InfoIcon } from "lucide-react";
|
||||
import LoggedInPopover from "./LoggedInPopover";
|
||||
import SignInPopoverButton from "./SignInPopoverButton";
|
||||
import InfoPopover from "../misc/InfoPopover";
|
||||
import { snowfallEvents } from "../misc/SnowfallController";
|
||||
|
||||
export default function TopBar({ inter }: { inter: string }) {
|
||||
const clerk = useClerk();
|
||||
@ -48,16 +47,8 @@ export default function TopBar({ inter }: { inter: string }) {
|
||||
return (
|
||||
<>
|
||||
<SignedOut>
|
||||
<div className="mt-1 gap-1 grid grid-cols-6">
|
||||
<div className="mt-1 gap-1 grid grid-cols-5">
|
||||
<SignInPopoverButton className="col-span-2" variant="outline" />
|
||||
<Button
|
||||
size="icon"
|
||||
variant="ghost"
|
||||
className="mb-1"
|
||||
onClick={() => snowfallEvents.emit("toggle")}
|
||||
>
|
||||
<CloudSnow className="h-[1.2rem] w-[1.2rem]" />
|
||||
</Button>
|
||||
<Popover>
|
||||
<PopoverTrigger>
|
||||
<Button size="icon" variant="ghost">
|
||||
@ -91,7 +82,7 @@ export default function TopBar({ inter }: { inter: string }) {
|
||||
</div>
|
||||
</SignedOut>
|
||||
<SignedIn>
|
||||
<div className="mt-1 grid grid-cols-5 gap-1">
|
||||
<div className="mt-1 grid grid-cols-4 gap-1">
|
||||
<Popover>
|
||||
<PopoverTrigger>
|
||||
<Button size="icon" variant="ghost" className="mb-1">
|
||||
@ -112,14 +103,6 @@ export default function TopBar({ inter }: { inter: string }) {
|
||||
<LoggedInPopover />
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<Button
|
||||
size="icon"
|
||||
variant="ghost"
|
||||
className="mb-1"
|
||||
onClick={() => snowfallEvents.emit("toggle")}
|
||||
>
|
||||
<CloudSnow className="h-[1.2rem] w-[1.2rem]" />
|
||||
</Button>
|
||||
<Popover>
|
||||
<PopoverTrigger>
|
||||
<Button size="icon" variant="ghost" className="mb-1">
|
||||
|
||||
@ -13,6 +13,7 @@ import NextTopLoader from "@/lib/top-loader";
|
||||
import Link from "next/link";
|
||||
import BannerContainer from "@/components/feat/BannerContainer";
|
||||
import { Inter } from "next/font/google";
|
||||
import useStatus from "@/lib/hooks/use-status";
|
||||
|
||||
const inter = Inter({ variable: "--font-inter", subsets: ["latin"] });
|
||||
export default function LayoutPart({
|
||||
@ -20,15 +21,22 @@ export default function LayoutPart({
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
const { loading, incidents, statusURL } = useStatus();
|
||||
|
||||
return (
|
||||
<>
|
||||
<BannerContainer
|
||||
className={"w-screen h-[3rem] border-b fixed backdrop-blur flex z-10"}
|
||||
className={
|
||||
"w-screen h-[3rem] border-b grid-cols-3 fixed backdrop-blur z-10 " +
|
||||
(!loading && (incidents as never as Array<any>).length > 0
|
||||
? "grid"
|
||||
: "flex")
|
||||
}
|
||||
style={(size: number) => ({
|
||||
marginTop: `${2 * size}rem`,
|
||||
})}
|
||||
>
|
||||
<div className="items-center me-auto mt-2 pl-7 max-sm:mt-3">
|
||||
<div className="items-center justify-self-start me-auto mt-2 pl-7 max-sm:mt-3 flex-1">
|
||||
<Breadcrumb>
|
||||
<BreadcrumbList>
|
||||
<Link href="/">
|
||||
@ -40,7 +48,30 @@ export default function LayoutPart({
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
</div>
|
||||
{!loading &&
|
||||
incidents !== null &&
|
||||
(incidents as Array<any>).length > 0 && (
|
||||
<div className="justify-self-center items-center text-center pb-2 pt-2 rounded border my-1 px-2 bg-red-500 text-white">
|
||||
<strong className="text-sm">
|
||||
{
|
||||
(
|
||||
incidents[0] as {
|
||||
attributes: { title: string };
|
||||
}
|
||||
).attributes.title
|
||||
}{" "}
|
||||
</strong>{" "}
|
||||
<span className="text-sm">- MHSF may be down</span>
|
||||
<br />
|
||||
<Link href={"https://" + statusURL} className="text-sm">
|
||||
View MHSF Status
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="justify-self-end">
|
||||
<TopBar inter={inter.className} />
|
||||
</div>
|
||||
</BannerContainer>
|
||||
<BannerContainer
|
||||
style={(size: number) => ({
|
||||
|
||||
29
src/components/feat/LinkingSetup.tsx
Normal file
29
src/components/feat/LinkingSetup.tsx
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* MHSF, Minehut Server List
|
||||
* All external content is rather licensed under the ECA Agreement
|
||||
* located here: https://mhsf.app/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.
|
||||
*/
|
||||
@ -1,4 +1,4 @@
|
||||
"use client";;
|
||||
"use client";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { z } from "zod";
|
||||
@ -43,7 +43,7 @@ export function BannerPopover({ server, get }: { server: string; get: any }) {
|
||||
}
|
||||
|
||||
return (
|
||||
<ColorProvider server={server} fetch={get}>
|
||||
<ColorProvider server={server} fetchV={get}>
|
||||
<div>
|
||||
<span className="text-sm">
|
||||
All images that are in a web supported format can be used as the
|
||||
|
||||
@ -78,7 +78,7 @@ export function DiscordPopover({ server, get }: { server: string; get: any }) {
|
||||
}, [get]);
|
||||
|
||||
return (
|
||||
<ColorProvider server={server} fetch={get}>
|
||||
<ColorProvider server={server} fetchV={get}>
|
||||
<div>
|
||||
<span className="text-sm">
|
||||
To embed a Discord server into your server page, first enable the
|
||||
|
||||
200
src/components/misc/DisplaySettings.tsx
Normal file
200
src/components/misc/DisplaySettings.tsx
Normal file
@ -0,0 +1,200 @@
|
||||
"use client";
|
||||
import { CircleAlert, LayoutGrid, List, Phone } from "lucide-react";
|
||||
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { Alert, AlertDescription, AlertTitle } from "../ui/alert";
|
||||
import { Select } from "@radix-ui/react-select";
|
||||
import {
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectSeparator,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "../ui/select";
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip";
|
||||
import { SignedIn } from "@clerk/nextjs";
|
||||
|
||||
export function DisplaySettings({
|
||||
presentationMode,
|
||||
setPresentationMode,
|
||||
selectedProperties,
|
||||
setSelectedProperties,
|
||||
hero,
|
||||
setHero,
|
||||
ipr,
|
||||
am,
|
||||
iprChangerCallback,
|
||||
padding,
|
||||
paddingChangerCallback,
|
||||
}: any) {
|
||||
const toggleProperty = (property: string) => {
|
||||
setSelectedProperties((prev: any) =>
|
||||
prev.includes(property)
|
||||
? prev.filter((p: any) => p !== property)
|
||||
: [...prev, property]
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-full space-y-6 bg-background">
|
||||
<Tabs
|
||||
defaultValue="cards"
|
||||
className="w-full"
|
||||
onValueChange={setPresentationMode}
|
||||
value={presentationMode}
|
||||
>
|
||||
<div className="border-b">
|
||||
<TabsList className="grid w-full grid-cols-2 bg-background p-0">
|
||||
<TabsTrigger
|
||||
value="grid"
|
||||
className="flex items-center gap-2 py-2.5 px-4 data-[state=active]:bg-background data-[state=active]:shadow-none rounded-none border-r"
|
||||
>
|
||||
<LayoutGrid className="h-4 w-4" />
|
||||
Grid
|
||||
</TabsTrigger>
|
||||
<TabsTrigger
|
||||
value="table"
|
||||
className="flex items-center gap-2 py-2.5 px-4 data-[state=active]:bg-background data-[state=active]:shadow-none rounded-none"
|
||||
>
|
||||
<List className="h-4 w-4" />
|
||||
Table
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
</div>
|
||||
|
||||
<TabsContent value="grid" className="space-y-6 mt-0 ">
|
||||
<SignedIn>
|
||||
<div className="flex items-center justify-between pt-5 pb-1 p-4">
|
||||
<Label htmlFor="set-hero" className="font-normal">
|
||||
Show hero at the top of the page
|
||||
</Label>
|
||||
<Switch id="set-hero" value={hero} onCheckedChange={setHero} />
|
||||
</div>
|
||||
</SignedIn>
|
||||
|
||||
<Separator />
|
||||
|
||||
<div
|
||||
className={
|
||||
"flex items-center justify-between py-1 " +
|
||||
(am ? "border border-orange-500 rounded px-2 mx-2" : "mx-4")
|
||||
}
|
||||
>
|
||||
<Label
|
||||
htmlFor="grid-columns"
|
||||
className="font-normal flex items-center"
|
||||
>
|
||||
{am && (
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<CircleAlert size={16} className="mr-2 text-orange-500" />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
If you change this setting, it will take priority over your{" "}
|
||||
<br />
|
||||
account settings. These settings will not save over reloads.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
Grid items p/ row
|
||||
</Label>
|
||||
<Select value={ipr} onValueChange={iprChangerCallback}>
|
||||
<SelectTrigger className="w-[125px]">
|
||||
<SelectValue placeholder="" id="grid-columns" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value="4">4 items</SelectItem>
|
||||
<SelectItem value="5">5 items</SelectItem>
|
||||
<SelectItem value="6">6 items</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div
|
||||
className={
|
||||
"flex items-center justify-between py-1 " +
|
||||
(am ? "border border-orange-500 rounded px-2 mx-2" : "mx-4")
|
||||
}
|
||||
>
|
||||
<Label htmlFor="padding" className="font-normal flex items-center">
|
||||
{am && (
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<CircleAlert size={16} className="mr-2 text-orange-500" />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
If you change this setting, it will take priority over your{" "}
|
||||
<br />
|
||||
account settings. These settings will not save over reloads.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
Padding
|
||||
</Label>
|
||||
<Select
|
||||
value={padding.toString()}
|
||||
onValueChange={paddingChangerCallback}
|
||||
>
|
||||
<SelectTrigger className="w-[125px]">
|
||||
<SelectValue placeholder="" id="padding" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value="0">Default</SelectItem>
|
||||
<SelectSeparator />
|
||||
<SelectItem value="15">15px</SelectItem>
|
||||
<SelectItem value="30">30px</SelectItem>
|
||||
<SelectItem value="40">40px</SelectItem>
|
||||
<SelectItem value="60">60px</SelectItem>
|
||||
<SelectItem value="100">100px</SelectItem>
|
||||
<SelectItem value="200">200px</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
|
||||
<div className="space-y-4 pt-1 p-4">
|
||||
<h3 className="text-xs uppercase text-gray-500">
|
||||
Display Properties
|
||||
</h3>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{["Author", "MOTD", "Tags", "Players Online", "Actions"].map(
|
||||
(property) => (
|
||||
<button
|
||||
key={property}
|
||||
onClick={() => toggleProperty(property)}
|
||||
className={cn(
|
||||
"px-3 py-1.5 text-sm rounded-md transition-colors",
|
||||
selectedProperties.includes(property)
|
||||
? "bg-secondary text-secondary-foreground border"
|
||||
: "hover:bg-muted/80"
|
||||
)}
|
||||
>
|
||||
{property}
|
||||
</button>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="table" className="mt-0 px-4 my-4">
|
||||
<Alert className="md:hidden">
|
||||
<Phone className="h-4 w-4" />
|
||||
<AlertTitle>Table mode isn't optimized for mobile</AlertTitle>
|
||||
<AlertDescription>
|
||||
At this time, we do not recommend using table mode on mobile.
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
134
src/components/misc/FilterMenu.tsx
Normal file
134
src/components/misc/FilterMenu.tsx
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* MHSF, Minehut Server List
|
||||
* All external content is rather licensed under the ECA Agreement
|
||||
* located here: https://mhsf.app/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.
|
||||
*/
|
||||
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuCheckboxItem,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuRadioGroup,
|
||||
DropdownMenuRadioItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuSub,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { Badge } from "../ui/badge";
|
||||
import { allCategories, allTags } from "@/config/tags";
|
||||
|
||||
export function FilterMenu({
|
||||
serverSizeChangerCallback,
|
||||
serverSizeChangerValueCallback,
|
||||
templateFilter,
|
||||
tagChangerValueCallback,
|
||||
tagChangerCallback,
|
||||
categoryChangerCallback,
|
||||
categoryChangerValueCallback,
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
serverSizeChangerCallback: any;
|
||||
serverSizeChangerValueCallback: any;
|
||||
templateFilter: any;
|
||||
tagChangerValueCallback: any;
|
||||
tagChangerCallback: any;
|
||||
categoryChangerCallback: any;
|
||||
categoryChangerValueCallback: any;
|
||||
}) {
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>{children}</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="max-h-[400px] overflow-auto">
|
||||
<DropdownMenuRadioGroup
|
||||
onValueChange={serverSizeChangerCallback}
|
||||
value={serverSizeChangerValueCallback()}
|
||||
>
|
||||
<DropdownMenuRadioItem value="smaller">
|
||||
<div className="block">
|
||||
Only allow smaller servers
|
||||
<br />
|
||||
<span className="text-sm text-muted-foreground">
|
||||
Only allow servers that have the player range 7-15, and cannot{" "}
|
||||
<br />
|
||||
be Always Online.
|
||||
</span>
|
||||
</div>
|
||||
</DropdownMenuRadioItem>
|
||||
<DropdownMenuRadioItem value="bigger">
|
||||
<div className="block">
|
||||
Only allow bigger servers
|
||||
<br />
|
||||
<span className="text-sm text-muted-foreground">
|
||||
Only allow servers with more than 15 players.
|
||||
</span>
|
||||
</div>
|
||||
</DropdownMenuRadioItem>
|
||||
<DropdownMenuRadioItem value="none">
|
||||
No/custom requirements
|
||||
</DropdownMenuRadioItem>
|
||||
</DropdownMenuRadioGroup>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuSub>
|
||||
<span className="text-sm text-muted-foreground ml-2">Tags</span>
|
||||
</DropdownMenuSub>
|
||||
{allTags.map((tag) => (
|
||||
<div key={tag.docsName}>
|
||||
{tag.docsName && tag.__filter == undefined && (
|
||||
<DropdownMenuCheckboxItem
|
||||
disabled={templateFilter && tag.__disab != undefined}
|
||||
id={tag.docsName}
|
||||
checked={tagChangerValueCallback(tag)}
|
||||
onCheckedChange={tagChangerCallback(tag)}
|
||||
>
|
||||
<Badge variant={tag.role} className="mr-1">
|
||||
{tag.docsName}
|
||||
</Badge>
|
||||
</DropdownMenuCheckboxItem>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuSub>
|
||||
<span className="text-sm text-muted-foreground ml-2">Categories</span>
|
||||
</DropdownMenuSub>
|
||||
{allCategories.map((categorie) => (
|
||||
<DropdownMenuCheckboxItem
|
||||
id={categorie.name}
|
||||
key={categorie.name}
|
||||
onCheckedChange={categoryChangerCallback(categorie)}
|
||||
checked={categoryChangerValueCallback(categorie)}
|
||||
>
|
||||
<Badge variant={categorie.role} className="mr-1">
|
||||
{categorie.name}
|
||||
</Badge>
|
||||
</DropdownMenuCheckboxItem>
|
||||
))}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
}
|
||||
74
src/components/misc/Footer.tsx
Normal file
74
src/components/misc/Footer.tsx
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* MHSF, Minehut Server List
|
||||
* All external content is rather licensed under the ECA Agreement
|
||||
* located here: https://mhsf.app/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";
|
||||
|
||||
import { Book } from "lucide-react";
|
||||
import { BrandingColorfulIcon } from "../Icon";
|
||||
import { Button } from "../ui/button";
|
||||
import Github from "../ui/github";
|
||||
import { Separator } from "../ui/separator";
|
||||
import Link from "next/link";
|
||||
import { useTheme } from "next-themes";
|
||||
|
||||
export default function Footer() {
|
||||
const { resolvedTheme } = useTheme();
|
||||
|
||||
return (
|
||||
<footer>
|
||||
<Separator />
|
||||
<p className="px-4 pt-8 pb-2">
|
||||
<span className="text-xl font-bold text-muted-foreground pb-12 flex items-center">
|
||||
<BrandingColorfulIcon className="w-12 h-12 mr-2" />
|
||||
MHSF
|
||||
</span>
|
||||
|
||||
<p>© {new Date().getFullYear()} dvelo</p>
|
||||
<strong className="text-sm">
|
||||
MHSF is built on open-source technologies and is not endorsed by or
|
||||
affiliated with GamerSafer or its subsidiaries.{" "}
|
||||
</strong>
|
||||
<br />
|
||||
<span className="flex items-center">
|
||||
<Link href="https://github.com/DeveloLongScript/MHSF">
|
||||
<Button variant="ghost" size="icon">
|
||||
<Github fill={resolvedTheme === "dark" ? "white" : "black"} />
|
||||
</Button>
|
||||
</Link>
|
||||
<Link href="/docs">
|
||||
<Button variant="ghost" size="icon">
|
||||
<Book size={14} />
|
||||
</Button>
|
||||
</Link>
|
||||
</span>
|
||||
</p>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
@ -29,44 +29,107 @@
|
||||
*/
|
||||
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { TextCopyComp } from "./TextCopyComp";
|
||||
import { ChevronDown, ChevronUp } from "lucide-react";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "../ui/tabs";
|
||||
import { Badge } from "../ui/badge";
|
||||
import Link from "next/link";
|
||||
import { Alert, AlertDescription, AlertTitle } from "../ui/alert";
|
||||
import { ServerOff } from "lucide-react";
|
||||
|
||||
export function ShowInfo() {
|
||||
const [open, setOpen] = useState(false);
|
||||
return (
|
||||
<div>
|
||||
{open == false && (
|
||||
<div
|
||||
className="text-blue-500 flex items-center cursor-pointer"
|
||||
onClick={() => setOpen(true)}
|
||||
<br />
|
||||
Choose a method:
|
||||
<Tabs defaultValue="preview" className="relative mr-auto w-full">
|
||||
<div className="flex items-center justify-between pb-3">
|
||||
<TabsList className="w-full justify-start rounded-none border-b bg-transparent p-0">
|
||||
<TabsTrigger
|
||||
value="coreboxx"
|
||||
className="relative h-9 rounded-none border-b-2 border-b-transparent bg-transparent px-4 pb-3 pt-2 font-semibold text-muted-foreground shadow-none transition-none data-[state=active]:border-b-primary data-[state=active]:text-foreground data-[state=active]:shadow-none"
|
||||
>
|
||||
More info <ChevronDown size={16} className="ml-2" />
|
||||
CoreBoxx <Badge className="ml-3">Recommended</Badge>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger
|
||||
value="mhsfpv"
|
||||
className="relative h-9 rounded-none border-b-2 border-b-transparent bg-transparent px-4 pb-3 pt-2 font-semibold text-muted-foreground shadow-none transition-none data-[state=active]:border-b-primary data-[state=active]:text-foreground data-[state=active]:shadow-none"
|
||||
>
|
||||
MHSFPV
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
</div>
|
||||
)}
|
||||
{open == true && (
|
||||
<>
|
||||
<TabsContent value="coreboxx">
|
||||
<p>
|
||||
By claiming your account, you can add Markdown descriptions and{" "}
|
||||
custom color schemes to your server (and more), making it stand out.
|
||||
To get started, join the server below on your Minecraft account.
|
||||
Enter the code in chat in the website, and you will link your
|
||||
account. You may need to go into the lobby and start the server.
|
||||
<Link href="/server/CoreBoxx" className="underline">
|
||||
CoreBoxx
|
||||
</Link>{" "}
|
||||
has partnered with us to have an integrated account linking feature,
|
||||
which is also open all day.
|
||||
</p>
|
||||
<br />
|
||||
<TextCopyComp />
|
||||
<p className="py-1">
|
||||
<code className="border rounded-full bg-muted h-[1.75rem] w-[1.75rem] absolute inline-flex items-center justify-center">
|
||||
1
|
||||
</code>
|
||||
<span className="ml-[2.25rem] pt-0.5 grid grid-rows-2">
|
||||
<span>Join CoreBoxx</span>
|
||||
|
||||
<code className="border rounded p-2">CoreBoxx.minehut.gg</code>
|
||||
</span>
|
||||
</p>
|
||||
<p className="py-1">
|
||||
<code className="border rounded-full bg-muted h-[1.75rem] w-[1.75rem] absolute inline-flex items-center justify-center">
|
||||
2
|
||||
</code>
|
||||
<span className="ml-[2.25rem] pt-0.5 grid">
|
||||
<span>
|
||||
Link your account using <code>/mhsf</code>
|
||||
</span>
|
||||
</span>
|
||||
</p>
|
||||
<p className="py-1">
|
||||
<code className="border rounded-full bg-muted h-[1.75rem] w-[1.75rem] absolute inline-flex items-center justify-center">
|
||||
3
|
||||
</code>
|
||||
<span className="ml-[2.25rem] pt-0.5 grid">
|
||||
<span>Input the code returned below</span>
|
||||
</span>
|
||||
</p>
|
||||
</TabsContent>
|
||||
<TabsContent value="mhsfpv">
|
||||
<Alert>
|
||||
<ServerOff className="h-4 w-4" />
|
||||
<AlertTitle>Server isn't online all day</AlertTitle>
|
||||
<AlertDescription>
|
||||
While joining MHSFPV, you may need to go into the lobby to start
|
||||
the server to then join.
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
<br />
|
||||
<p>
|
||||
MHSFPV is a Minehut server dedicated to linking your account on
|
||||
MHSF.
|
||||
</p>
|
||||
<br />
|
||||
<div
|
||||
className="text-blue-500 flex items-center cursor-pointer"
|
||||
onClick={() => setOpen(false)}
|
||||
>
|
||||
Less info <ChevronUp size={16} className="ml-2" />
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<p className="py-1">
|
||||
<code className="border rounded-full bg-muted h-[1.75rem] w-[1.75rem] absolute inline-flex items-center justify-center">
|
||||
1
|
||||
</code>
|
||||
<span className="ml-[2.25rem] pt-0.5 grid grid-rows-2">
|
||||
<span>Join MHSFPV</span>
|
||||
|
||||
<code className="border rounded p-2">MHSFPV.minehut.gg</code>
|
||||
</span>
|
||||
</p>
|
||||
<p className="py-1">
|
||||
<code className="border rounded-full bg-muted h-[1.75rem] w-[1.75rem] absolute inline-flex items-center justify-center">
|
||||
2
|
||||
</code>
|
||||
<span className="ml-[2.25rem] pt-0.5 grid">
|
||||
<span>Input the code in chat below</span>
|
||||
</span>
|
||||
</p>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -83,15 +83,20 @@ export default function CodeDialog({
|
||||
});
|
||||
async function onSubmit(data: z.infer<typeof FormSchema>) {
|
||||
const { code } = data;
|
||||
const playerName = await toast.promise(
|
||||
new Promise(async (g, b) => {
|
||||
const response = await linkMCAccount(code);
|
||||
|
||||
if (response == undefined) {
|
||||
toast.promise(
|
||||
new Promise<void>((g, b) => {
|
||||
linkMCAccount(code).then((c) => {
|
||||
console.log(c);
|
||||
if (c === undefined) {
|
||||
b();
|
||||
return;
|
||||
}
|
||||
g(response);
|
||||
g();
|
||||
|
||||
setName(c);
|
||||
setDialog(true);
|
||||
setLinked(true);
|
||||
});
|
||||
}),
|
||||
{
|
||||
loading: "Linking account..",
|
||||
@ -99,9 +104,6 @@ export default function CodeDialog({
|
||||
success: "Linked account!",
|
||||
}
|
||||
);
|
||||
setName(playerName as string);
|
||||
setDialog(true);
|
||||
setLinked(true);
|
||||
}
|
||||
|
||||
return (
|
||||
@ -156,9 +158,9 @@ export default function CodeDialog({
|
||||
<DialogTitle>You have linked your account!</DialogTitle>
|
||||
<Confetti className="absolute left-0 top-0 z-0 size-full" />
|
||||
<DialogDescription>
|
||||
You've successfully linked your account, <strong>{name}</strong>!
|
||||
Enjoy adding banners, custom accent colors, and other things to
|
||||
your server page.
|
||||
You've successfully linked your account, {name}! Enjoy adding
|
||||
banners, custom accent colors, and other things to your server
|
||||
page.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
</DialogContent>
|
||||
|
||||
@ -31,7 +31,7 @@
|
||||
|
||||
import { DatabaseZap } from "lucide-react";
|
||||
|
||||
export default function NoItems() {
|
||||
export default function NoItems({ title }: { title?: string }) {
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-col items-center justify-center p-4 pt-10">
|
||||
@ -40,7 +40,9 @@ export default function NoItems() {
|
||||
size={32}
|
||||
/>
|
||||
<p className="text-xl text-gray-600 mt-2">
|
||||
Huh, we tried to find something, but nothing was found.
|
||||
{title
|
||||
? title
|
||||
: "Huh, we tried to find something, but nothing was found."}
|
||||
</p>
|
||||
</div>
|
||||
</>
|
||||
|
||||
158
src/components/misc/ServerListInterface.tsx
Normal file
158
src/components/misc/ServerListInterface.tsx
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* MHSF, Minehut Server List
|
||||
* All external content is rather licensed under the ECA Agreement
|
||||
* located here: https://mhsf.app/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.
|
||||
*/
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import {
|
||||
ChevronDown,
|
||||
Dices,
|
||||
ListRestart,
|
||||
MoreVertical,
|
||||
Search,
|
||||
SquareTerminal,
|
||||
} from "lucide-react";
|
||||
import { FilterMenu } from "./FilterMenu";
|
||||
import { DisplaySettings } from "./DisplaySettings";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover";
|
||||
import events from "@/lib/commandEvent";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "../ui/dropdown-menu";
|
||||
|
||||
export default function ServerListInterface({
|
||||
linksProps,
|
||||
viewProps,
|
||||
refreshCallback,
|
||||
pickRandomServerCallback,
|
||||
}: {
|
||||
linksProps: {
|
||||
serverSizeChangerCallback: any;
|
||||
serverSizeChangerValueCallback: any;
|
||||
templateFilter: any;
|
||||
tagChangerValueCallback: any;
|
||||
tagChangerCallback: any;
|
||||
categoryChangerCallback: any;
|
||||
categoryChangerValueCallback: any;
|
||||
};
|
||||
viewProps: {
|
||||
setPresentationMode: any;
|
||||
presentationMode: any;
|
||||
selectedProperties: any;
|
||||
setSelectedProperties: any;
|
||||
hero: any;
|
||||
setHero: any;
|
||||
iprChangerCallback: any;
|
||||
ipr: any;
|
||||
am: any;
|
||||
padding: any;
|
||||
paddingChangerCallback: any;
|
||||
};
|
||||
refreshCallback: any;
|
||||
pickRandomServerCallback: any;
|
||||
}) {
|
||||
return (
|
||||
<div className="w-full mt-6">
|
||||
<div className="flex flex-col sm:flex-row items-stretch sm:items-center sm:justify-between gap-2 sm:gap-8">
|
||||
<div className="grid grid-cols-2 sm:flex sm:flex-row items-stretch sm:items-center gap-2">
|
||||
<FilterMenu {...linksProps}>
|
||||
<Button variant="outline" className="w-full gap-2">
|
||||
Filter
|
||||
<ChevronDown className="h-4 w-4" />
|
||||
</Button>
|
||||
</FilterMenu>
|
||||
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<Button variant="outline" className="w-full gap-2">
|
||||
Display
|
||||
<ChevronDown className="h-4 w-4" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-80 p-0">
|
||||
<DisplaySettings {...viewProps} />
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2 w-full sm:w-auto">
|
||||
<div className="relative flex-1">
|
||||
<Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
|
||||
<Input
|
||||
type="search"
|
||||
placeholder="Search..."
|
||||
className="pl-8"
|
||||
value=""
|
||||
onClick={(c) => {
|
||||
c.preventDefault();
|
||||
events.emit("search-request-event");
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" size="icon" className="shrink-0">
|
||||
<MoreVertical className="h-4 w-4" />
|
||||
<span className="sr-only">More options</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuItem
|
||||
className="dark:text-white py-2"
|
||||
onSelect={refreshCallback}
|
||||
>
|
||||
<ListRestart />
|
||||
Reload Servers
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
className="dark:text-white py-2"
|
||||
onSelect={pickRandomServerCallback}
|
||||
>
|
||||
<Dices />
|
||||
Pick Random Server
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem
|
||||
className="dark:text-white py-2"
|
||||
onSelect={() => events.emit("cmd-event")}
|
||||
>
|
||||
<SquareTerminal />
|
||||
Show Command Bar
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
59
src/components/ui/alert.tsx
Normal file
59
src/components/ui/alert.tsx
Normal file
@ -0,0 +1,59 @@
|
||||
import * as React from "react"
|
||||
import { cva, type VariantProps } from "class-variance-authority"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const alertVariants = cva(
|
||||
"relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-background text-foreground",
|
||||
destructive:
|
||||
"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
const Alert = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>
|
||||
>(({ className, variant, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
role="alert"
|
||||
className={cn(alertVariants({ variant }), className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
Alert.displayName = "Alert"
|
||||
|
||||
const AlertTitle = React.forwardRef<
|
||||
HTMLParagraphElement,
|
||||
React.HTMLAttributes<HTMLHeadingElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<h5
|
||||
ref={ref}
|
||||
className={cn("mb-1 font-medium leading-none tracking-tight", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
AlertTitle.displayName = "AlertTitle"
|
||||
|
||||
const AlertDescription = React.forwardRef<
|
||||
HTMLParagraphElement,
|
||||
React.HTMLAttributes<HTMLParagraphElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn("text-sm [&_p]:leading-relaxed", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
AlertDescription.displayName = "AlertDescription"
|
||||
|
||||
export { Alert, AlertTitle, AlertDescription }
|
||||
@ -1,15 +1,20 @@
|
||||
import { useTheme } from "next-themes";
|
||||
import type { SVGProps } from "react";
|
||||
const Github = (props: SVGProps<SVGSVGElement>) => (
|
||||
const Github = (props: SVGProps<SVGSVGElement>) => {
|
||||
const { resolvedTheme } = useTheme();
|
||||
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 256 250"
|
||||
width="1em"
|
||||
height="1em"
|
||||
fill="#fff"
|
||||
fill={resolvedTheme === "dark" ? "#fff" : "#24292f"}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
preserveAspectRatio="xMidYMid"
|
||||
{...props}
|
||||
>
|
||||
<path d="M128.001 0C57.317 0 0 57.307 0 128.001c0 56.554 36.676 104.535 87.535 121.46 6.397 1.185 8.746-2.777 8.746-6.158 0-3.052-.12-13.135-.174-23.83-35.61 7.742-43.124-15.103-43.124-15.103-5.823-14.795-14.213-18.73-14.213-18.73-11.613-7.944.876-7.78.876-7.78 12.853.902 19.621 13.19 19.621 13.19 11.417 19.568 29.945 13.911 37.249 10.64 1.149-8.272 4.466-13.92 8.127-17.116-28.431-3.236-58.318-14.212-58.318-63.258 0-13.975 5-25.394 13.188-34.358-1.329-3.224-5.71-16.242 1.24-33.874 0 0 10.749-3.44 35.21 13.121 10.21-2.836 21.16-4.258 32.038-4.307 10.878.049 21.837 1.47 32.066 4.307 24.431-16.56 35.165-13.12 35.165-13.12 6.967 17.63 2.584 30.65 1.255 33.873 8.207 8.964 13.173 20.383 13.173 34.358 0 49.163-29.944 59.988-58.447 63.157 4.591 3.972 8.682 11.762 8.682 23.704 0 17.126-.148 30.91-.148 35.126 0 3.407 2.304 7.398 8.792 6.14C219.37 232.5 256 184.537 256 128.002 256 57.307 198.691 0 128.001 0Zm-80.06 182.34c-.282.636-1.283.827-2.194.39-.929-.417-1.45-1.284-1.15-1.922.276-.655 1.279-.838 2.205-.399.93.418 1.46 1.293 1.139 1.931Zm6.296 5.618c-.61.566-1.804.303-2.614-.591-.837-.892-.994-2.086-.375-2.66.63-.566 1.787-.301 2.626.591.838.903 1 2.088.363 2.66Zm4.32 7.188c-.785.545-2.067.034-2.86-1.104-.784-1.138-.784-2.503.017-3.05.795-.547 2.058-.055 2.861 1.075.782 1.157.782 2.522-.019 3.08Zm7.304 8.325c-.701.774-2.196.566-3.29-.49-1.119-1.032-1.43-2.496-.726-3.27.71-.776 2.213-.558 3.315.49 1.11 1.03 1.45 2.505.701 3.27Zm9.442 2.81c-.31 1.003-1.75 1.459-3.199 1.033-1.448-.439-2.395-1.613-2.103-2.626.301-1.01 1.747-1.484 3.207-1.028 1.446.436 2.396 1.602 2.095 2.622Zm10.744 1.193c.036 1.055-1.193 1.93-2.715 1.95-1.53.034-2.769-.82-2.786-1.86 0-1.065 1.202-1.932 2.733-1.958 1.522-.03 2.768.818 2.768 1.868Zm10.555-.405c.182 1.03-.875 2.088-2.387 2.37-1.485.271-2.861-.365-3.05-1.386-.184-1.056.893-2.114 2.376-2.387 1.514-.263 2.868.356 3.061 1.403Z" />
|
||||
</svg>
|
||||
);
|
||||
);
|
||||
};
|
||||
export default Github;
|
||||
|
||||
@ -99,6 +99,15 @@ export const allTags: Array<{
|
||||
role: "secondary",
|
||||
__filter: true,
|
||||
},
|
||||
{
|
||||
name: async () => "Partner",
|
||||
condition: async (s) => s.name === "CoreBoxx",
|
||||
tooltipDesc: "This server is a partner with MHSF.",
|
||||
docsName: "Partner",
|
||||
htmlDocs: "This tag represents that this server is a partner with MHSF.",
|
||||
primary: true,
|
||||
role: "purple",
|
||||
},
|
||||
// deprecated
|
||||
/**{
|
||||
name: async () => "Velocity",
|
||||
@ -280,12 +289,11 @@ export const allCategories: Array<{
|
||||
async function requestServer(s: OnlineServer): Promise<ServerResponse> {
|
||||
if (serverCache[s.name] === undefined) {
|
||||
const re = await fetch(
|
||||
"https://api.minehut.com/server/" + s.name + "?byName=true",
|
||||
"https://api.minehut.com/server/" + s.name + "?byName=true"
|
||||
);
|
||||
const json = await re.json();
|
||||
serverCache[s.name] = json.server;
|
||||
return json.server;
|
||||
} else {
|
||||
return serverCache[s.name];
|
||||
}
|
||||
return serverCache[s.name];
|
||||
}
|
||||
|
||||
@ -30,6 +30,9 @@
|
||||
|
||||
"use client";
|
||||
import A from "@/components/misc/Link";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import Github from "@/components/ui/github";
|
||||
import Link from "next/link";
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
const User = ({ user }: { user: string }) => (
|
||||
@ -41,13 +44,22 @@ const User = ({ user }: { user: string }) => (
|
||||
const FeatureList = ({
|
||||
features,
|
||||
title,
|
||||
github,
|
||||
}: {
|
||||
features: (string | ReactNode)[];
|
||||
github?: string;
|
||||
title: ReactNode;
|
||||
}) => {
|
||||
return (
|
||||
<ul>
|
||||
{title}
|
||||
{github && (
|
||||
<Link href={github}>
|
||||
<Button variant="ghost" size="sm">
|
||||
<Github className="mr-1" /> Release
|
||||
</Button>
|
||||
</Link>
|
||||
)}
|
||||
{features.map((feature, i) => (
|
||||
<li key={i}>• {feature}</li>
|
||||
))}
|
||||
@ -55,13 +67,42 @@ const FeatureList = ({
|
||||
);
|
||||
};
|
||||
|
||||
export const version = "1.6.50";
|
||||
export const version = "1.7.0";
|
||||
export const changelog: { name: string; id: string; changelog: ReactNode }[] = [
|
||||
{
|
||||
id: "38ufajf8efajwj3njdaisef",
|
||||
name: "v1.7",
|
||||
changelog: (
|
||||
<FeatureList
|
||||
github="https://github.com/DeveloLongScript/MHSF/releases/tag/1.7"
|
||||
features={[
|
||||
"Partnered with CoreBoxx!",
|
||||
"You can now link your Minecraft account on CoreBoxx! (check out CB 3.0.15)",
|
||||
"Revamped the server finding controls",
|
||||
"Fixed various bugs",
|
||||
"Made banners a different style",
|
||||
"Made Discord embed not inside a card",
|
||||
"Added incorrect server capitalization detection",
|
||||
"Made the MOTD area slightly bigger",
|
||||
"New footer",
|
||||
"Added padding for settings page",
|
||||
"Added new table mode",
|
||||
"Added new button for GitHub release on changelog",
|
||||
]}
|
||||
title={
|
||||
<strong className="flex items-center">
|
||||
Version 1.7 (January 18th 2025)
|
||||
</strong>
|
||||
}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "dut6hx3f2paswzjve4yg9r",
|
||||
name: "v1.6.5",
|
||||
changelog: (
|
||||
<FeatureList
|
||||
github="https://github.com/DeveloLongScript/MHSF/releases/tag/1.6.5"
|
||||
features={[
|
||||
"New MOTD engine that is over 3,000% faster, runs client-side, and doesn't need any requests to run.",
|
||||
"Fixed issue where GitHub link was broken if you were signed-out",
|
||||
@ -80,6 +121,7 @@ export const changelog: { name: string; id: string; changelog: ReactNode }[] = [
|
||||
name: "v1.6.0",
|
||||
changelog: (
|
||||
<FeatureList
|
||||
github="https://github.com/DeveloLongScript/MHSF/releases/tag/1.6"
|
||||
features={[
|
||||
"Completely redid top of server view",
|
||||
"Favorite counts are now prominent on the server view",
|
||||
@ -102,6 +144,7 @@ export const changelog: { name: string; id: string; changelog: ReactNode }[] = [
|
||||
name: "v1.5.0",
|
||||
changelog: (
|
||||
<FeatureList
|
||||
github="https://github.com/DeveloLongScript/MHSF/releases/tag/1.5"
|
||||
features={[
|
||||
"New embeds",
|
||||
"More mobile friendly elements",
|
||||
@ -121,6 +164,7 @@ export const changelog: { name: string; id: string; changelog: ReactNode }[] = [
|
||||
name: "v1.4.5",
|
||||
changelog: (
|
||||
<FeatureList
|
||||
github="https://github.com/DeveloLongScript/MHSF/releases/tag/1.4.5"
|
||||
features={["Add server icons"]}
|
||||
title={
|
||||
<strong className="flex items-center">
|
||||
@ -135,6 +179,7 @@ export const changelog: { name: string; id: string; changelog: ReactNode }[] = [
|
||||
name: "v1.4.0",
|
||||
changelog: (
|
||||
<FeatureList
|
||||
github="https://github.com/DeveloLongScript/MHSF/releases/tag/1.4"
|
||||
features={[
|
||||
"Revamped documentation",
|
||||
"Revamped changelog UI",
|
||||
|
||||
@ -290,7 +290,6 @@ export async function unlinkMCAccount(): Promise<boolean> {
|
||||
const response = await fetch(
|
||||
connector(`/account-linking/unlink-account`, { version: 0 }),
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
|
||||
@ -28,32 +28,22 @@
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
"use client";
|
||||
import { CommandEvents } from "@/lib/commandEvent";
|
||||
import { useEffect, useState } from "react";
|
||||
import Snowfall from "react-snowfall";
|
||||
|
||||
export const snowfallEvents = new CommandEvents();
|
||||
export default function SnowfallController() {
|
||||
const [visible, setVisible] = useState(true);
|
||||
export default function useStatus() {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [incidents, setIncidents] = useState(null);
|
||||
const [statusURL, setStatusURL] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
snowfallEvents.on("toggle", () => {
|
||||
setVisible(!visible);
|
||||
fetch("/api/v1/get-status")
|
||||
.then((c) => c.json())
|
||||
.then((d) => {
|
||||
setLoading(false);
|
||||
setIncidents(d.incidents);
|
||||
setStatusURL(d.url);
|
||||
});
|
||||
}, [visible]);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
{visible && (
|
||||
<Snowfall
|
||||
style={{
|
||||
position: "fixed",
|
||||
width: "100vw",
|
||||
height: "100vh",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
return { loading, incidents, statusURL };
|
||||
}
|
||||
@ -61,7 +61,10 @@ export default async function handler(
|
||||
const collection = db.collection("owned-servers");
|
||||
|
||||
if ((await collection.findOne({ server: server })) == undefined) {
|
||||
const mh = await fetch("https://api.minehut.com/servers", {
|
||||
const mh = await fetch(
|
||||
process.env.MHSF_BACKEND_API_LOCATION ??
|
||||
"https://api.minehut.com/servers",
|
||||
{
|
||||
headers: {
|
||||
accept: "*/*",
|
||||
"accept-language": Math.random().toString(),
|
||||
@ -74,10 +77,12 @@ export default async function handler(
|
||||
"sec-fetch-site": "cross-site",
|
||||
Referer: "http://localhost:3000/",
|
||||
"Referrer-Policy": "strict-origin-when-cross-origin",
|
||||
Authentication: `MHSF-Backend-Server ${process.env.MHSF_BACKEND_API_LOCATION ? process.env.MHSF_BACKEND_SECRET : "Sorry Minehut Devs."}`,
|
||||
},
|
||||
body: null,
|
||||
method: "GET",
|
||||
});
|
||||
}
|
||||
);
|
||||
const servers: Array<OnlineServer> = (await mh.json()).servers;
|
||||
|
||||
servers.forEach(async (c, i) => {
|
||||
|
||||
@ -46,13 +46,13 @@ export default async function handler(
|
||||
|
||||
const db = client.db(process.env.CUSTOM_MONGO_DB ?? "mhsf");
|
||||
const users = db.collection("claimed-users");
|
||||
const user = await (await clerkClient()).users.getUser(userId);
|
||||
|
||||
if (user.publicMetadata.player == undefined) {
|
||||
if ((await users.find({ userId }).toArray()).length === 0) {
|
||||
res.status(400).send({ result: "Hasn't linked yet!" });
|
||||
return;
|
||||
}
|
||||
await users.findOneAndDelete({ player: user.publicMetadata.player });
|
||||
await users.findOneAndDelete({ userId });
|
||||
const user = await (await clerkClient()).users.getUser(userId);
|
||||
|
||||
await (
|
||||
await clerkClient()
|
||||
).users.updateUserMetadata(userId, {
|
||||
|
||||
61
src/pages/api/v1/get-status.ts
Normal file
61
src/pages/api/v1/get-status.ts
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* MHSF, Minehut Server List
|
||||
* All external content is rather licensed under the ECA Agreement
|
||||
* located here: https://mhsf.app/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.
|
||||
*/
|
||||
import { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse
|
||||
) {
|
||||
const betterStackResult = await fetch(
|
||||
`https://uptime.betterstack.com/api/v2/status-pages/${process.env.BS_STATUS_PAGE}/status-reports`,
|
||||
{ headers: { Authorization: `Bearer ${process.env.BS_TOKEN}` } }
|
||||
);
|
||||
const betterStackURL = await fetch(
|
||||
`https://uptime.betterstack.com/api/v2/status-pages/${process.env.BS_STATUS_PAGE}`,
|
||||
{ headers: { Authorization: `Bearer ${process.env.BS_TOKEN}` } }
|
||||
);
|
||||
|
||||
const result = await betterStackResult.json();
|
||||
const url = await betterStackURL.json();
|
||||
|
||||
const filtered = result.data.filter(
|
||||
(c: any) =>
|
||||
c.attributes.ends_at === null &&
|
||||
c.attributes.affected_resources.filter(
|
||||
(v: any) =>
|
||||
v.status_page_resource_id === process.env.BS_STATUS_MAIN_WEBSITE
|
||||
).length > 0
|
||||
);
|
||||
|
||||
res.status(200).send({
|
||||
url: url.data.attributes.custom_domain,
|
||||
incidents: filtered,
|
||||
});
|
||||
}
|
||||
22
yarn.lock
22
yarn.lock
@ -373,6 +373,11 @@
|
||||
ts-pattern "^4.3.0"
|
||||
type-fest "^3.12.0"
|
||||
|
||||
"@corex/deepmerge@^4.0.43":
|
||||
version "4.0.43"
|
||||
resolved "https://registry.yarnpkg.com/@corex/deepmerge/-/deepmerge-4.0.43.tgz#9bd42559ebb41cc5a7fb7cfeea5f231c20977dca"
|
||||
integrity sha512-N8uEMrMPL0cu/bdboEWpQYb/0i2K5Qn8eCsxzOmxSggJbbQte7ljMRoXm917AbntqTGOzdTu+vP3KOOzoC70HQ==
|
||||
|
||||
"@discordjs/builders@^1.8.2":
|
||||
version "1.8.2"
|
||||
resolved "https://registry.yarnpkg.com/@discordjs/builders/-/builders-1.8.2.tgz#535d970331ee40f20dec9ef8079e43092f323ce9"
|
||||
@ -841,6 +846,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@next/env/-/env-14.2.10.tgz#1d3178340028ced2d679f84140877db4f420333c"
|
||||
integrity sha512-dZIu93Bf5LUtluBXIv4woQw2cZVZ2DJTjax5/5DOs3lzEOeKLy7GxRSr4caK9/SCPdaW6bCgpye6+n4Dh9oJPw==
|
||||
|
||||
"@next/env@^13.4.3":
|
||||
version "13.5.8"
|
||||
resolved "https://registry.yarnpkg.com/@next/env/-/env-13.5.8.tgz#404d3b3e5881b6a0510500c6cc97e3589a2e6371"
|
||||
integrity sha512-YmiG58BqyZ2FjrF2+5uZExL2BrLr8RTQzLXNDJ8pJr0O+rPlOeDPXp1p1/4OrR3avDidzZo3D8QO2cuDv1KCkw==
|
||||
|
||||
"@next/eslint-plugin-next@14.2.3":
|
||||
version "14.2.3"
|
||||
resolved "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.3.tgz"
|
||||
@ -6326,7 +6336,7 @@ minimessage-js@^1.1.3:
|
||||
resolved "https://registry.yarnpkg.com/minimessage-js/-/minimessage-js-1.1.3.tgz#ded53108d686e681cfb2071c2db60b6ae2da60db"
|
||||
integrity sha512-dP7O/JVfRwMwFl/8KQALtKa+Vo4Za3ihgcSLVB6X3k/fjZWhA8SDQBJ1xUZu0NB6mslkzrIE1Xo+EHYcSXGtQw==
|
||||
|
||||
minimist@^1.2.0, minimist@^1.2.6:
|
||||
minimist@^1.2.0, minimist@^1.2.6, minimist@^1.2.8:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz"
|
||||
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
|
||||
@ -6443,6 +6453,16 @@ next-css-obfuscator@^2.2.16:
|
||||
recoverable-random "^1.0.5"
|
||||
yargs "^17.7.2"
|
||||
|
||||
next-sitemap@^4.2.3:
|
||||
version "4.2.3"
|
||||
resolved "https://registry.yarnpkg.com/next-sitemap/-/next-sitemap-4.2.3.tgz#5db3f650351a51e84b9fd6b58c5af2f9257b5058"
|
||||
integrity sha512-vjdCxeDuWDzldhCnyFCQipw5bfpl4HmZA7uoo3GAaYGjGgfL4Cxb1CiztPuWGmS+auYs7/8OekRS8C2cjdAsjQ==
|
||||
dependencies:
|
||||
"@corex/deepmerge" "^4.0.43"
|
||||
"@next/env" "^13.4.3"
|
||||
fast-glob "^3.2.12"
|
||||
minimist "^1.2.8"
|
||||
|
||||
next-themes@^0.4.3:
|
||||
version "0.4.3"
|
||||
resolved "https://registry.yarnpkg.com/next-themes/-/next-themes-0.4.3.tgz#ea54552d5986936d177eed393ea50b658ae44800"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user