file uploader
This commit is contained in:
@@ -31,8 +31,8 @@
|
||||
"@preact/signals": "https://esm.sh/*@preact/signals@1.1.3",
|
||||
"@preact/signals-core": "https://esm.sh/*@preact/signals-core@1.2.3",
|
||||
"$std/": "https://deno.land/std@0.193.0/",
|
||||
"puppet": "https://deno.land/x/sockpuppet@0.6.0/mod.ts",
|
||||
"puppet/client": "https://deno.land/x/sockpuppet@0.6.0/client/mod.ts"
|
||||
"puppet": "https://deno.land/x/sockpuppet@0.6.1/mod.ts",
|
||||
"puppet/client": "https://deno.land/x/sockpuppet@0.6.1/client/mod.ts"
|
||||
},
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
|
42
fresh.gen.ts
42
fresh.gen.ts
@@ -8,16 +8,19 @@ import * as $2 from "./routes/api/fabric/index.ts";
|
||||
import * as $3 from "./routes/api/manage.ts";
|
||||
import * as $4 from "./routes/api/players.ts";
|
||||
import * as $5 from "./routes/index.tsx";
|
||||
import * as $6 from "./routes/players.tsx";
|
||||
import * as $7 from "./routes/properties.tsx";
|
||||
import * as $8 from "./routes/setup/eula.tsx";
|
||||
import * as $9 from "./routes/setup/fabric.tsx";
|
||||
import * as $10 from "./routes/setup/index.tsx";
|
||||
import * as $11 from "./routes/terminal.tsx";
|
||||
import * as $6 from "./routes/mods/index.tsx";
|
||||
import * as $7 from "./routes/players.tsx";
|
||||
import * as $8 from "./routes/properties.tsx";
|
||||
import * as $9 from "./routes/setup/eula.tsx";
|
||||
import * as $10 from "./routes/setup/fabric.tsx";
|
||||
import * as $11 from "./routes/setup/index.tsx";
|
||||
import * as $12 from "./routes/terminal.tsx";
|
||||
import * as $13 from "./routes/upload.ts";
|
||||
import * as $$0 from "./islands/fabricVersions.tsx";
|
||||
import * as $$1 from "./islands/players.tsx";
|
||||
import * as $$2 from "./islands/statusManager.tsx";
|
||||
import * as $$3 from "./islands/terminal.tsx";
|
||||
import * as $$1 from "./islands/fileUploader.tsx";
|
||||
import * as $$2 from "./islands/players.tsx";
|
||||
import * as $$3 from "./islands/statusManager.tsx";
|
||||
import * as $$4 from "./islands/terminal.tsx";
|
||||
|
||||
const manifest = {
|
||||
routes: {
|
||||
@@ -27,18 +30,21 @@ const manifest = {
|
||||
"./routes/api/manage.ts": $3,
|
||||
"./routes/api/players.ts": $4,
|
||||
"./routes/index.tsx": $5,
|
||||
"./routes/players.tsx": $6,
|
||||
"./routes/properties.tsx": $7,
|
||||
"./routes/setup/eula.tsx": $8,
|
||||
"./routes/setup/fabric.tsx": $9,
|
||||
"./routes/setup/index.tsx": $10,
|
||||
"./routes/terminal.tsx": $11,
|
||||
"./routes/mods/index.tsx": $6,
|
||||
"./routes/players.tsx": $7,
|
||||
"./routes/properties.tsx": $8,
|
||||
"./routes/setup/eula.tsx": $9,
|
||||
"./routes/setup/fabric.tsx": $10,
|
||||
"./routes/setup/index.tsx": $11,
|
||||
"./routes/terminal.tsx": $12,
|
||||
"./routes/upload.ts": $13,
|
||||
},
|
||||
islands: {
|
||||
"./islands/fabricVersions.tsx": $$0,
|
||||
"./islands/players.tsx": $$1,
|
||||
"./islands/statusManager.tsx": $$2,
|
||||
"./islands/terminal.tsx": $$3,
|
||||
"./islands/fileUploader.tsx": $$1,
|
||||
"./islands/players.tsx": $$2,
|
||||
"./islands/statusManager.tsx": $$3,
|
||||
"./islands/terminal.tsx": $$4,
|
||||
},
|
||||
baseUrl: import.meta.url,
|
||||
};
|
||||
|
71
islands/fileUploader.tsx
Normal file
71
islands/fileUploader.tsx
Normal file
@@ -0,0 +1,71 @@
|
||||
import { useState } from "preact/hooks";
|
||||
import { FunctionComponent } from "preact";
|
||||
|
||||
export const FileUploader: FunctionComponent<{ path: string }> = (
|
||||
{ children, path },
|
||||
) => {
|
||||
const [hovered, setHovered] = useState(false);
|
||||
|
||||
const playSound = () => {
|
||||
const sound = new Audio(
|
||||
"https://cdn.pixabay.com/audio/2023/07/21/audio_5634777127.mp3",
|
||||
);
|
||||
sound.play();
|
||||
};
|
||||
|
||||
const defaultPreventer = (e: Event) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
const uploadFiles = async (files: File[]) => {
|
||||
if (!files.length) return;
|
||||
|
||||
const formData = new FormData();
|
||||
for (const file of files) {
|
||||
formData.append(file.name, file);
|
||||
}
|
||||
|
||||
await fetch("/upload", {
|
||||
method: "POST",
|
||||
body: formData,
|
||||
headers: {
|
||||
"x-grizz-path": path,
|
||||
},
|
||||
});
|
||||
|
||||
location.reload();
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
class="relative grid"
|
||||
onDragEnter={(e) => {
|
||||
defaultPreventer(e);
|
||||
setHovered(true);
|
||||
}}
|
||||
onDragOver={(e) => {
|
||||
defaultPreventer(e);
|
||||
setHovered(true);
|
||||
}}
|
||||
onDrop={(e) => {
|
||||
defaultPreventer(e);
|
||||
playSound();
|
||||
const files = Array.from(e.dataTransfer?.files || []);
|
||||
uploadFiles(files);
|
||||
setHovered(false);
|
||||
}}
|
||||
onDragLeave={(e) => {
|
||||
defaultPreventer(e);
|
||||
setHovered(false);
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
{hovered && (
|
||||
<div class="absolute place-self-center">
|
||||
<i class="fas fa-cloud-arrow-up fa-4x"></i>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
112
lib/modrinth.ts
Normal file
112
lib/modrinth.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
import { Loader } from "../types/mcgrizzconf.ts";
|
||||
|
||||
export type ModrinthProjectSearchResult = {
|
||||
project_id: string;
|
||||
project_type: string;
|
||||
slug: string;
|
||||
author: string;
|
||||
title: string;
|
||||
description: string;
|
||||
categories: string[];
|
||||
display_categories: string[];
|
||||
versions: string[];
|
||||
downloads: number;
|
||||
follows: number;
|
||||
icon_url: string;
|
||||
date_created: string;
|
||||
date_modified: string;
|
||||
latest_version: string;
|
||||
license: string;
|
||||
client_side: string;
|
||||
server_side: string;
|
||||
gallery: string[];
|
||||
featured_gallery: string;
|
||||
color: number;
|
||||
};
|
||||
|
||||
export type ModrinthProject = {
|
||||
id: string;
|
||||
slug: string;
|
||||
project_type: string;
|
||||
team: string;
|
||||
title: string;
|
||||
description: string;
|
||||
// Markdown
|
||||
body: string;
|
||||
body_url: string | null;
|
||||
published: string;
|
||||
updated: string;
|
||||
approved: string;
|
||||
queued: string;
|
||||
status: string;
|
||||
requested_status: string;
|
||||
moderator_message: string | null;
|
||||
license: {
|
||||
id: string;
|
||||
name: string;
|
||||
url: string | null;
|
||||
};
|
||||
client_side: string;
|
||||
server_side: string;
|
||||
downloads: number;
|
||||
followers: number;
|
||||
categories: string[];
|
||||
additional_categories: [];
|
||||
game_versions: string[];
|
||||
loaders: string[];
|
||||
versions: string[];
|
||||
icon_url: string;
|
||||
issues_url: string;
|
||||
source_url: string;
|
||||
wiki_url: string | null;
|
||||
discord_url: string;
|
||||
donation_urls: string[];
|
||||
gallery: {
|
||||
url: string;
|
||||
featured: boolean;
|
||||
title: string;
|
||||
description: string;
|
||||
created: string;
|
||||
ordering: number;
|
||||
}[];
|
||||
color: number;
|
||||
thread_id: string;
|
||||
monetization_status: string;
|
||||
};
|
||||
|
||||
export class Modrinth {
|
||||
static apiRoot = "https://api.modrinth.com/v2";
|
||||
|
||||
static async searchMods(
|
||||
q: string,
|
||||
version: string,
|
||||
loader: Loader,
|
||||
offset = 0,
|
||||
limit = 12,
|
||||
) {
|
||||
const facets = [
|
||||
`"versions:${version}"`,
|
||||
'"project_type:mod"',
|
||||
];
|
||||
|
||||
if (loader && loader !== "vanilla" && loader !== "unset") {
|
||||
facets.push(`"categories:${loader}"`);
|
||||
}
|
||||
const qString = `/search?query=${q}&facets=[[${
|
||||
facets.join("],[")
|
||||
}]]&offset=${offset * limit}&limit=${limit}`.trim();
|
||||
|
||||
const res = await fetch(this.apiRoot + qString);
|
||||
return await res.json() as {
|
||||
hits: ModrinthProjectSearchResult;
|
||||
offset: number;
|
||||
limit: number;
|
||||
total_hits: number;
|
||||
};
|
||||
}
|
||||
|
||||
static async getProject(id: string) {
|
||||
const res = await fetch(this.apiRoot + "/project/" + id);
|
||||
return await res.json() as ModrinthProject;
|
||||
}
|
||||
}
|
@@ -21,7 +21,7 @@ export default function App({ Component }: AppProps) {
|
||||
>
|
||||
</link>
|
||||
<link rel="stylesheet" href="/styles/tailwind.css" />
|
||||
</head>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css" integrity="sha512-z3gLpd7yknf1YoNbCzqRKc4qyor8gaKU1qmn+CShxbuBusANI9QpRohGBreCFkKxLhei6S9CQXFEbbKuqLg0DA==" crossOrigin="anonymous" referrerpolicy="no-referrer" /> </head>
|
||||
<body>
|
||||
<div class="flex h-[100vh]">
|
||||
<div class="relative h-full min-w-[400px] bg-licorice overflow-y-auto border-r-2 p-4 dark:border-sky-950 border-sky text-white flex flex-col">
|
||||
|
61
routes/mods/index.tsx
Normal file
61
routes/mods/index.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import { FunctionComponent } from "preact";
|
||||
import { Content } from "../../components/Content.tsx";
|
||||
import { SERVER_STATE } from "../../state/serverState.ts";
|
||||
import { FileUploader } from "../../islands/fileUploader.tsx";
|
||||
|
||||
export default async function ModsFolder() {
|
||||
const files: string[] = [];
|
||||
if (
|
||||
SERVER_STATE.serverType !== "unset" && SERVER_STATE.serverType !== "vanilla"
|
||||
) {
|
||||
for await (const fileEntry of Deno.readDir("./server/mods")) {
|
||||
if (fileEntry.isFile) {
|
||||
files.push(fileEntry.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="container p-8">
|
||||
<Content>
|
||||
<h2 class="font-pixel text-xl">Active Mods</h2>
|
||||
<FileUploader path="./server/mods">
|
||||
<div className="relative grid lg:grid-cols-3 min-h-[100px]">
|
||||
{!files.length && (
|
||||
<div class="absolute place-self-center">Drop files here to upload</div>
|
||||
)}
|
||||
{files.map((f) => (
|
||||
<div class="flex gap-2 items-center">
|
||||
<FileIcon fileName={f} />
|
||||
{f}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</FileUploader>
|
||||
</Content>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const FileIcon: FunctionComponent<{ fileName: string }> = ({ fileName }) => {
|
||||
let icon;
|
||||
switch (fileName.split(".")[1]) {
|
||||
case "jar":
|
||||
icon = "fa-brand fa-java";
|
||||
break;
|
||||
case "tmp":
|
||||
case "temp":
|
||||
icon = "fas fa-ghost";
|
||||
break;
|
||||
case "png":
|
||||
case "jpg":
|
||||
case "jpeg":
|
||||
case "webp":
|
||||
icon = "fas fa-image";
|
||||
break;
|
||||
default:
|
||||
icon = "fas fa-file";
|
||||
}
|
||||
|
||||
return <i class={icon}></i>;
|
||||
};
|
21
routes/upload.ts
Normal file
21
routes/upload.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { Handlers } from "$fresh/server.ts";
|
||||
import { ensureFile } from "$std/fs/ensure_file.ts";
|
||||
|
||||
export const handler: Handlers = {
|
||||
async POST(req, _ctx) {
|
||||
const path = req.headers.get("x-grizz-path");
|
||||
if (!path) return new Response("Upload path not included", { status: 400 });
|
||||
|
||||
const files = Array.from((await req.formData()).values()) as File[];
|
||||
|
||||
for (const file of files) {
|
||||
const filePath = path.replace(/.$/, (e) => e.replace("/", "") + "/") +
|
||||
file.name;
|
||||
await ensureFile(filePath);
|
||||
const newFile = await Deno.open(filePath, { write: true });
|
||||
file.stream().pipeTo(newFile.writable);
|
||||
}
|
||||
|
||||
return new Response("Success");
|
||||
},
|
||||
};
|
@@ -1,7 +1,7 @@
|
||||
import { Sockpuppet } from "puppet/client";
|
||||
import { acceptEULA, checkEULA } from "../util/EULA.ts";
|
||||
import { Loader } from "../types/mcgrizzconf.ts";
|
||||
import { updateConfFile } from "../util/confFile.ts";
|
||||
import { getConfFile, updateConfFile } from "../util/confFile.ts";
|
||||
import { IS_BROWSER } from "$fresh/runtime.ts";
|
||||
|
||||
type MCServerEvent = 'message';
|
||||
@@ -16,7 +16,7 @@ class ServerState {
|
||||
private command!: Deno.Command;
|
||||
private process!: Deno.ChildProcess;
|
||||
|
||||
private _eulaAccepted: boolean;
|
||||
private _eulaAccepted = false;
|
||||
|
||||
private sockpuppet!: Sockpuppet;
|
||||
private _channelId = "blanaba";
|
||||
@@ -30,15 +30,29 @@ class ServerState {
|
||||
|
||||
private _serverType: Loader = 'unset';
|
||||
public get serverType(): Loader {
|
||||
return this.serverType;
|
||||
return this._serverType;
|
||||
}
|
||||
public set serverType(loader: Loader) {
|
||||
updateConfFile({loader});
|
||||
this._serverType = loader;
|
||||
}
|
||||
|
||||
private _serverVersion: string;
|
||||
public get serverVersion(): string {
|
||||
return this._serverVersion;
|
||||
}
|
||||
public set serverVersion(version: string) {
|
||||
updateConfFile({version});
|
||||
this._serverVersion = version;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
this._eulaAccepted = checkEULA();
|
||||
const conf = getConfFile();
|
||||
this._serverType = conf.loader;
|
||||
this._serverVersion = conf.version;
|
||||
|
||||
// if (this.serverType !== 'unset') this._eulaAccepted = checkEULA();
|
||||
|
||||
this.sockpuppet = new Sockpuppet(
|
||||
"ws://sockpuppet.cyborggrizzly.com",
|
||||
() => {
|
||||
|
BIN
static/javaicon.png
Normal file
BIN
static/javaicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 133 KiB |
File diff suppressed because one or more lines are too long
469
test.json
Normal file
469
test.json
Normal file
@@ -0,0 +1,469 @@
|
||||
{
|
||||
"hits": [
|
||||
{
|
||||
"project_id": "FTeXqI9v",
|
||||
"project_type": "mod",
|
||||
"slug": "create-new-age",
|
||||
"author": "nullBlade",
|
||||
"title": "Create: New Age",
|
||||
"description": "Create: New Age is an addon for the Create mod that adds integration with electricity.",
|
||||
"categories": ["technology", "fabric", "forge"],
|
||||
"display_categories": ["technology", "fabric", "forge"],
|
||||
"versions": ["1.19.2", "1.20.1", "1.20.2"],
|
||||
"downloads": 473,
|
||||
"follows": 10,
|
||||
"icon_url": "https://cdn.modrinth.com/data/FTeXqI9v/fe75695f6f2e085ac9fb56204de7f88b6d716e8d.png",
|
||||
"date_created": "2023-08-30T02:15:52.063627Z",
|
||||
"date_modified": "2023-09-24T07:07:15.073267Z",
|
||||
"latest_version": "1.20.2",
|
||||
"license": "BSD-3-Clause",
|
||||
"client_side": "required",
|
||||
"server_side": "required",
|
||||
"gallery": [
|
||||
"https://cdn.modrinth.com/data/FTeXqI9v/images/156cd2e6ce38d8647a7c1e073753baaebb7c0474.png",
|
||||
"https://cdn.modrinth.com/data/FTeXqI9v/images/197a77d6e98b80486481a7b7fe7cb28fa8b87f30.png",
|
||||
"https://cdn.modrinth.com/data/FTeXqI9v/images/59be34a6c51e72f31616917af146d02c0a5a3cb3.png",
|
||||
"https://cdn.modrinth.com/data/FTeXqI9v/images/e35cc2dc1e0aa47bc15fa2ef1aa9f2121f4d0539.png"
|
||||
],
|
||||
"featured_gallery": "https://cdn.modrinth.com/data/FTeXqI9v/images/8bdaf7546c4d46ff9305ed9aba18df6e32d9234a.jpeg",
|
||||
"color": 3220514
|
||||
},
|
||||
{
|
||||
"project_id": "nr7cSJlY",
|
||||
"project_type": "mod",
|
||||
"slug": "brewery",
|
||||
"author": "Patbox",
|
||||
"title": "Patbox's Brewery",
|
||||
"description": "Create alcoholic and non-alcoholic drinks with cauldrons and barrels!",
|
||||
"categories": ["food", "game-mechanics", "fabric", "quilt"],
|
||||
"display_categories": ["food", "game-mechanics", "fabric", "quilt"],
|
||||
"versions": [
|
||||
"1.19.2",
|
||||
"1.19.3",
|
||||
"1.19.4",
|
||||
"1.19.4-rc2",
|
||||
"1.20",
|
||||
"1.20.1",
|
||||
"1.20.2",
|
||||
"1.20.2-rc2",
|
||||
"1.20-rc1"
|
||||
],
|
||||
"downloads": 3924,
|
||||
"follows": 45,
|
||||
"icon_url": "https://cdn.modrinth.com/data/nr7cSJlY/c9c1d9b61922adda30b53d739922231c18d2823c.png",
|
||||
"date_created": "2022-09-25T20:30:15.568551Z",
|
||||
"date_modified": "2023-09-21T13:19:47.739240Z",
|
||||
"latest_version": "1.20-rc1",
|
||||
"license": "LGPL-3.0-only",
|
||||
"client_side": "optional",
|
||||
"server_side": "required",
|
||||
"gallery": [],
|
||||
"featured_gallery": "https://cdn.modrinth.com/data/nr7cSJlY/images/8965a6402256474bb5d7a5ff7141751f1f22992a.png",
|
||||
"color": 13625834
|
||||
},
|
||||
{
|
||||
"project_id": "sUlkLN1E",
|
||||
"project_type": "mod",
|
||||
"slug": "azure-paxels",
|
||||
"author": "AzureDoom",
|
||||
"title": "Azure Paxels",
|
||||
"description": "Created becasue Fabric 1.19.4 has no good paxel mods updated.",
|
||||
"categories": ["equipment", "fabric", "neoforge", "quilt"],
|
||||
"display_categories": ["equipment", "fabric", "neoforge", "quilt"],
|
||||
"versions": [
|
||||
"1.19.4",
|
||||
"1.20",
|
||||
"1.20.1",
|
||||
"1.20.2",
|
||||
"1.20-pre1",
|
||||
"1.20-rc1"
|
||||
],
|
||||
"downloads": 573,
|
||||
"follows": 10,
|
||||
"icon_url": "https://cdn.modrinth.com/data/sUlkLN1E/1e026932468f5dc227444892b11cc5e06f1587a7.png",
|
||||
"date_created": "2023-05-07T01:19:46.079261Z",
|
||||
"date_modified": "2023-10-03T18:20:58.140878Z",
|
||||
"latest_version": "1.20-rc1",
|
||||
"license": "MIT",
|
||||
"client_side": "required",
|
||||
"server_side": "required",
|
||||
"gallery": [
|
||||
"https://cdn.modrinth.com/data/sUlkLN1E/images/2f5f219a20627ab1e3d344d99eb4e725848df1b7.png"
|
||||
],
|
||||
"featured_gallery": null,
|
||||
"color": 3549487
|
||||
},
|
||||
{
|
||||
"project_id": "llV8wfkk",
|
||||
"project_type": "mod",
|
||||
"slug": "betterconsolemc",
|
||||
"author": "Jonas_Jones",
|
||||
"title": "BetterConsoleMC",
|
||||
"description": "Create custom ingame commads that run system commands and tasks.\nThis is a new and improved version of the ConsoleMC mod. It works by defining the command first to avoid the big security risk.",
|
||||
"categories": ["utility", "fabric", "quilt", "transportation"],
|
||||
"display_categories": ["utility", "fabric", "quilt"],
|
||||
"versions": [
|
||||
"1.17.1",
|
||||
"1.18",
|
||||
"1.18.1",
|
||||
"1.18.2",
|
||||
"1.19",
|
||||
"1.19.1",
|
||||
"1.19.2",
|
||||
"1.19.3",
|
||||
"1.19.4",
|
||||
"1.20",
|
||||
"1.20.1",
|
||||
"1.20.2"
|
||||
],
|
||||
"downloads": 119,
|
||||
"follows": 3,
|
||||
"icon_url": "https://cdn.modrinth.com/data/llV8wfkk/04f4393f5149d5b29a20b5170ac57eb4dfb7f303.png",
|
||||
"date_created": "2022-12-16T01:35:12.431459Z",
|
||||
"date_modified": "2023-09-26T21:59:10.564546Z",
|
||||
"latest_version": "1.20.2",
|
||||
"license": "CC0-1.0",
|
||||
"client_side": "unsupported",
|
||||
"server_side": "required",
|
||||
"gallery": [],
|
||||
"featured_gallery": null,
|
||||
"color": 16516316
|
||||
},
|
||||
{
|
||||
"project_id": "NWvsqJ2Z",
|
||||
"project_type": "mod",
|
||||
"slug": "areas",
|
||||
"author": "Serilum",
|
||||
"title": "Areas",
|
||||
"description": "✍️ Create custom named regions/towns/zones with a radius using signs, with join/leave messages via GUI.",
|
||||
"categories": [
|
||||
"decoration",
|
||||
"game-mechanics",
|
||||
"library",
|
||||
"fabric",
|
||||
"forge",
|
||||
"neoforge",
|
||||
"quilt"
|
||||
],
|
||||
"display_categories": [
|
||||
"decoration",
|
||||
"game-mechanics",
|
||||
"library",
|
||||
"fabric",
|
||||
"forge",
|
||||
"neoforge",
|
||||
"quilt"
|
||||
],
|
||||
"versions": [
|
||||
"1.16.5",
|
||||
"1.18.2",
|
||||
"1.19.2",
|
||||
"1.19.3",
|
||||
"1.19.4",
|
||||
"1.20",
|
||||
"1.20.1",
|
||||
"1.20.2"
|
||||
],
|
||||
"downloads": 96662,
|
||||
"follows": 114,
|
||||
"icon_url": "https://cdn.modrinth.com/data/NWvsqJ2Z/icon.png",
|
||||
"date_created": "2022-09-01T15:43:14.157586Z",
|
||||
"date_modified": "2023-09-22T00:10:53.971185Z",
|
||||
"latest_version": "1.20.2",
|
||||
"license": "LicenseRef-All-Rights-Reserved",
|
||||
"client_side": "required",
|
||||
"server_side": "optional",
|
||||
"gallery": [],
|
||||
"featured_gallery": null,
|
||||
"color": 4234903
|
||||
},
|
||||
{
|
||||
"project_id": "Ot5JFxuv",
|
||||
"project_type": "mod",
|
||||
"slug": "death-backup",
|
||||
"author": "Serilum",
|
||||
"title": "Death Backup",
|
||||
"description": "💾 Creates back-ups of player inventories before death, which can be loaded via commands.",
|
||||
"categories": [
|
||||
"management",
|
||||
"utility",
|
||||
"fabric",
|
||||
"forge",
|
||||
"neoforge",
|
||||
"quilt"
|
||||
],
|
||||
"display_categories": [
|
||||
"management",
|
||||
"utility",
|
||||
"fabric",
|
||||
"forge",
|
||||
"neoforge",
|
||||
"quilt"
|
||||
],
|
||||
"versions": [
|
||||
"1.16.5",
|
||||
"1.18.2",
|
||||
"1.19.2",
|
||||
"1.19.3",
|
||||
"1.19.4",
|
||||
"1.20",
|
||||
"1.20.1",
|
||||
"1.20.2"
|
||||
],
|
||||
"downloads": 2684,
|
||||
"follows": 23,
|
||||
"icon_url": "https://cdn.modrinth.com/data/Ot5JFxuv/icon.jpg",
|
||||
"date_created": "2022-09-01T14:40:08.430843Z",
|
||||
"date_modified": "2023-09-21T23:20:00.640383Z",
|
||||
"latest_version": "1.20.2",
|
||||
"license": "LicenseRef-All-Rights-Reserved",
|
||||
"client_side": "optional",
|
||||
"server_side": "required",
|
||||
"gallery": [],
|
||||
"featured_gallery": null,
|
||||
"color": 5655906
|
||||
},
|
||||
{
|
||||
"project_id": "IPbFTPzw",
|
||||
"project_type": "mod",
|
||||
"slug": "quick-paths",
|
||||
"author": "Serilum",
|
||||
"title": "Quick Paths",
|
||||
"description": "🚶 Create long paths instantly by setting a start and end point.",
|
||||
"categories": [
|
||||
"transportation",
|
||||
"utility",
|
||||
"fabric",
|
||||
"forge",
|
||||
"neoforge",
|
||||
"quilt"
|
||||
],
|
||||
"display_categories": [
|
||||
"transportation",
|
||||
"utility",
|
||||
"fabric",
|
||||
"forge",
|
||||
"neoforge",
|
||||
"quilt"
|
||||
],
|
||||
"versions": [
|
||||
"1.16.5",
|
||||
"1.18.2",
|
||||
"1.19.2",
|
||||
"1.19.3",
|
||||
"1.19.4",
|
||||
"1.20",
|
||||
"1.20.1",
|
||||
"1.20.2"
|
||||
],
|
||||
"downloads": 2213,
|
||||
"follows": 25,
|
||||
"icon_url": "https://cdn.modrinth.com/data/IPbFTPzw/icon.jpg",
|
||||
"date_created": "2022-09-01T09:45:53.732436Z",
|
||||
"date_modified": "2023-09-21T22:01:33.176715Z",
|
||||
"latest_version": "1.20.2",
|
||||
"license": "LicenseRef-All-Rights-Reserved",
|
||||
"client_side": "optional",
|
||||
"server_side": "required",
|
||||
"gallery": [],
|
||||
"featured_gallery": null,
|
||||
"color": 6455609
|
||||
},
|
||||
{
|
||||
"project_id": "fgmhI8kH",
|
||||
"project_type": "mod",
|
||||
"slug": "ct-overhaul-village",
|
||||
"author": "ChoiceTheorem",
|
||||
"title": "ChoiceTheorem's Overhauled Village",
|
||||
"description": "Enhances and creates new villages and pillager outposts, that perfectly fit into your Minecraft world.",
|
||||
"categories": [
|
||||
"adventure",
|
||||
"worldgen",
|
||||
"fabric",
|
||||
"forge",
|
||||
"neoforge",
|
||||
"quilt",
|
||||
"economy",
|
||||
"utility"
|
||||
],
|
||||
"display_categories": [
|
||||
"adventure",
|
||||
"worldgen",
|
||||
"fabric",
|
||||
"forge",
|
||||
"neoforge",
|
||||
"quilt"
|
||||
],
|
||||
"versions": [
|
||||
"1.18.2",
|
||||
"1.18.2-rc1",
|
||||
"1.19",
|
||||
"1.19.1",
|
||||
"1.19.2",
|
||||
"1.19.3",
|
||||
"1.19.4",
|
||||
"1.20",
|
||||
"1.20.1",
|
||||
"1.20.2"
|
||||
],
|
||||
"downloads": 158413,
|
||||
"follows": 630,
|
||||
"icon_url": "https://cdn.modrinth.com/data/fgmhI8kH/76dd7230a35c12d4956985317ffd0c079d6a9148.jpeg",
|
||||
"date_created": "2022-05-16T03:06:55.644362Z",
|
||||
"date_modified": "2023-09-29T16:52:26.973688Z",
|
||||
"latest_version": "1.20.2",
|
||||
"license": "CC-BY-NC-ND-4.0",
|
||||
"client_side": "optional",
|
||||
"server_side": "required",
|
||||
"gallery": [
|
||||
"https://cdn.modrinth.com/data/fgmhI8kH/images/2f7b8e2fc46cbb9e7a83368a93ab1ba1feb110ed.webp",
|
||||
"https://cdn.modrinth.com/data/fgmhI8kH/images/576fb3e920f242512932434a51cba40b14da2750.png"
|
||||
],
|
||||
"featured_gallery": "https://cdn.modrinth.com/data/fgmhI8kH/images/15d7bf1aa1b7174fde4a5dac2ed81d4b8adb4b06.png",
|
||||
"color": 5587502
|
||||
},
|
||||
{
|
||||
"project_id": "kOuPUitF",
|
||||
"project_type": "mod",
|
||||
"slug": "healing-campfire",
|
||||
"author": "Serilum",
|
||||
"title": "Healing Campfire",
|
||||
"description": "🔥🩹 Creates an area around the (soul) campfire where players and passive mobs receive regeneration.",
|
||||
"categories": [
|
||||
"adventure",
|
||||
"game-mechanics",
|
||||
"utility",
|
||||
"fabric",
|
||||
"forge",
|
||||
"neoforge",
|
||||
"quilt"
|
||||
],
|
||||
"display_categories": [
|
||||
"adventure",
|
||||
"game-mechanics",
|
||||
"utility",
|
||||
"fabric",
|
||||
"forge",
|
||||
"neoforge",
|
||||
"quilt"
|
||||
],
|
||||
"versions": [
|
||||
"1.16.5",
|
||||
"1.18.2",
|
||||
"1.19.2",
|
||||
"1.19.3",
|
||||
"1.19.4",
|
||||
"1.20",
|
||||
"1.20.1",
|
||||
"1.20.2"
|
||||
],
|
||||
"downloads": 16604,
|
||||
"follows": 111,
|
||||
"icon_url": "https://cdn.modrinth.com/data/kOuPUitF/icon.png",
|
||||
"date_created": "2022-09-01T13:26:56.104570Z",
|
||||
"date_modified": "2023-09-21T22:40:49.277734Z",
|
||||
"latest_version": "1.20.2",
|
||||
"license": "LicenseRef-All-Rights-Reserved",
|
||||
"client_side": "optional",
|
||||
"server_side": "required",
|
||||
"gallery": [],
|
||||
"featured_gallery": null,
|
||||
"color": 5921840
|
||||
},
|
||||
{
|
||||
"project_id": "QktnymFN",
|
||||
"project_type": "mod",
|
||||
"slug": "lightning-podoboo",
|
||||
"author": "LostLuma",
|
||||
"title": "Lightning Podoboo",
|
||||
"description": "Makes fire created by natural lightning cosmetic, meaning no blocks are destroyed during thunderstorms.",
|
||||
"categories": ["game-mechanics", "utility", "fabric", "quilt", "mobs"],
|
||||
"display_categories": ["game-mechanics", "utility", "fabric", "quilt"],
|
||||
"versions": [
|
||||
"1.18",
|
||||
"1.18.1",
|
||||
"1.18.2",
|
||||
"1.19",
|
||||
"1.19.1",
|
||||
"1.19.2",
|
||||
"1.19.3",
|
||||
"1.19.4",
|
||||
"1.20",
|
||||
"1.20.1",
|
||||
"1.20.2"
|
||||
],
|
||||
"downloads": 488,
|
||||
"follows": 12,
|
||||
"icon_url": "",
|
||||
"date_created": "2022-02-08T11:09:41.222962Z",
|
||||
"date_modified": "2023-09-21T16:15:18.747778Z",
|
||||
"latest_version": "1.20.2",
|
||||
"license": "MIT",
|
||||
"client_side": "optional",
|
||||
"server_side": "required",
|
||||
"gallery": [],
|
||||
"featured_gallery": null,
|
||||
"color": null
|
||||
},
|
||||
{
|
||||
"project_id": "hQbzUScT",
|
||||
"project_type": "mod",
|
||||
"slug": "dynamichud",
|
||||
"author": "tanishisherewithhh",
|
||||
"title": "DynamicHUD",
|
||||
"description": "A library to create Hud Widgets and display them on the screen. AutoSave and Autoload included. Fabric only",
|
||||
"categories": ["game-mechanics", "library", "utility", "fabric"],
|
||||
"display_categories": ["game-mechanics", "library", "utility", "fabric"],
|
||||
"versions": ["1.19.4", "1.20", "1.20.1", "1.20.2"],
|
||||
"downloads": 249,
|
||||
"follows": 6,
|
||||
"icon_url": "https://cdn.modrinth.com/data/hQbzUScT/76bde52a3696a533af510f47e8f93b35ad4eb2ab.png",
|
||||
"date_created": "2023-06-17T00:27:34.710323Z",
|
||||
"date_modified": "2023-10-02T06:26:09.404685Z",
|
||||
"latest_version": "1.20.2",
|
||||
"license": "MIT",
|
||||
"client_side": "required",
|
||||
"server_side": "unsupported",
|
||||
"gallery": [
|
||||
"https://cdn.modrinth.com/data/hQbzUScT/images/76bde52a3696a533af510f47e8f93b35ad4eb2ab.png"
|
||||
],
|
||||
"featured_gallery": "https://cdn.modrinth.com/data/hQbzUScT/images/de25273afeb40a17b77821ae4b56434c3953a47b.png",
|
||||
"color": 9757053
|
||||
},
|
||||
{
|
||||
"project_id": "O5BnVXcp",
|
||||
"project_type": "mod",
|
||||
"slug": "shulker-nbt-fix",
|
||||
"author": "qpcrummer",
|
||||
"title": "ShulkerNbtFix",
|
||||
"description": "All shulkers are created equal: placed and unplaced",
|
||||
"categories": ["game-mechanics", "fabric", "quilt", "utility"],
|
||||
"display_categories": ["game-mechanics", "fabric", "quilt"],
|
||||
"versions": [
|
||||
"1.19",
|
||||
"1.19.1",
|
||||
"1.19.2",
|
||||
"1.19.3",
|
||||
"1.19.4",
|
||||
"1.20",
|
||||
"1.20.1",
|
||||
"1.20.2"
|
||||
],
|
||||
"downloads": 120,
|
||||
"follows": 4,
|
||||
"icon_url": "https://cdn.modrinth.com/data/O5BnVXcp/096802aeb7ee5284d3dca7f38b6e00b46c1530ce.png",
|
||||
"date_created": "2023-06-17T00:38:18.136269Z",
|
||||
"date_modified": "2023-09-22T00:16:16.841957Z",
|
||||
"latest_version": "1.20.2",
|
||||
"license": "LGPL-3.0-only",
|
||||
"client_side": "unsupported",
|
||||
"server_side": "required",
|
||||
"gallery": [],
|
||||
"featured_gallery": null,
|
||||
"color": 5980251
|
||||
}
|
||||
],
|
||||
"offset": 0,
|
||||
"limit": 12,
|
||||
"total_hits": 23
|
||||
}
|
@@ -1,5 +1,13 @@
|
||||
export type Loader = 'forge' | 'fabric' | 'vanilla' | 'unset';
|
||||
import { ModrinthProject } from "../lib/modrinth.ts";
|
||||
|
||||
export type Loader = "forge" | "fabric" | "vanilla" | "unset";
|
||||
|
||||
export type MCGrizzConf = {
|
||||
loader: Loader
|
||||
}
|
||||
loader: Loader;
|
||||
version: string;
|
||||
mods?: {
|
||||
source: "modrinth";
|
||||
details: ModrinthProject;
|
||||
jarName?: string;
|
||||
}[];
|
||||
};
|
||||
|
@@ -3,7 +3,6 @@ import { IS_BROWSER } from "$fresh/runtime.ts";
|
||||
const eulaRegex = /(eula=false)/;
|
||||
export const checkEULA = (instance = "server") =>
|
||||
!IS_BROWSER && !eulaRegex.test(Deno.readTextFileSync(`./${instance}/eula.txt`));
|
||||
// true;
|
||||
|
||||
export const acceptEULA = (instance = "server") => {
|
||||
const eula = Deno.readTextFileSync(`./${instance}/eula.txt`);
|
||||
|
@@ -1,7 +1,10 @@
|
||||
import { ensureFileSync } from "$std/fs/ensure_file.ts";
|
||||
import { IS_BROWSER } from "$fresh/runtime.ts";
|
||||
import { MCGrizzConf } from "../types/mcgrizzconf.ts";
|
||||
|
||||
const defaultConf: MCGrizzConf = {
|
||||
loader: 'unset',
|
||||
version: ''
|
||||
}
|
||||
|
||||
const confPath = 'mcgrizz.json'
|
||||
@@ -14,7 +17,9 @@ export function makeConfFile(): MCGrizzConf {
|
||||
}
|
||||
|
||||
export function getConfFile(): MCGrizzConf {
|
||||
const conf = JSON.parse(Deno.readTextFileSync(confPath));
|
||||
if (IS_BROWSER) return defaultConf;
|
||||
ensureFileSync(confPath);
|
||||
const conf = JSON.parse(Deno.readTextFileSync(confPath) || 'null');
|
||||
|
||||
if (!conf) {
|
||||
return makeConfFile();
|
||||
@@ -24,7 +29,8 @@ export function getConfFile(): MCGrizzConf {
|
||||
}
|
||||
|
||||
export async function updateConfFile(newConf: Partial<MCGrizzConf>) {
|
||||
const conf = {...getConfFile(), newConf};
|
||||
if (IS_BROWSER) return;
|
||||
const conf = {...getConfFile(), ...newConf};
|
||||
|
||||
await Deno.writeTextFile(confPath, JSON.stringify(conf, null, 2));
|
||||
}
|
||||
|
35
util/download.ts
Normal file
35
util/download.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { ensureFile } from "$std/fs/ensure_file.ts";
|
||||
|
||||
/**
|
||||
*
|
||||
* @param src url of file
|
||||
* @param dest destination file. If `useFileName` is true, this should be the destination directory
|
||||
* @param [useFileName] whether to use the inferred file name from `src`
|
||||
*/
|
||||
|
||||
export async function downloadFile(src: string, dest: string, useFileName?:boolean) {
|
||||
if (!(src.startsWith("http://") || src.startsWith("https://"))) {
|
||||
throw new TypeError("URL must start with be http:// or https://");
|
||||
}
|
||||
|
||||
const fileName = src.split('/').at(-1);
|
||||
|
||||
const resp = await fetch(src);
|
||||
if (!resp.ok) {
|
||||
throw new Deno.errors.BadResource(
|
||||
`Request failed with status ${resp.status}`,
|
||||
);
|
||||
} else if (!resp.body) {
|
||||
throw new Deno.errors.UnexpectedEof(
|
||||
`The download url ${src} doesn't contain a file to download`,
|
||||
);
|
||||
} else if (resp.status === 404) {
|
||||
throw new Deno.errors.NotFound(
|
||||
`The requested url "${src}" could not be found`,
|
||||
);
|
||||
}
|
||||
|
||||
await ensureFile(useFileName ? dest + fileName : dest);
|
||||
const file = await Deno.open(dest, { truncate: true, write: true });
|
||||
resp.body.pipeTo(file.writable);
|
||||
}
|
@@ -1,3 +1,4 @@
|
||||
// deno-lint-ignore-file no-fallthrough
|
||||
import { MCGrizzConf } from "../types/mcgrizzconf.ts";
|
||||
import { NavItem } from "../types/nav.ts";
|
||||
import { makeConfFile } from "./confFile.ts";
|
||||
@@ -13,16 +14,20 @@ export function getNavItems(): NavItem[] {
|
||||
conf = makeConfFile();
|
||||
}
|
||||
|
||||
const items: NavItem[] = [];
|
||||
|
||||
switch (conf.loader) {
|
||||
case "unset":
|
||||
return [{
|
||||
items.push({
|
||||
title: "Setup",
|
||||
href: "/",
|
||||
}];
|
||||
});
|
||||
break;
|
||||
case "forge":
|
||||
case "fabric":
|
||||
items.push({ title: "Mods", href: "/mods" });
|
||||
case "vanilla":
|
||||
return [
|
||||
items.unshift(
|
||||
{
|
||||
title: "Server Terminal",
|
||||
href: "/terminal",
|
||||
@@ -35,6 +40,8 @@ export function getNavItems(): NavItem[] {
|
||||
title: "Server Properties",
|
||||
href: "/properties",
|
||||
},
|
||||
];
|
||||
);
|
||||
break;
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import { ensureFile } from "$std/fs/ensure_file.ts";
|
||||
import { SERVER_STATE } from "../state/serverState.ts";
|
||||
import { filterTruthy } from "./filters.ts";
|
||||
|
||||
@@ -30,7 +31,7 @@ export const getPlayerData = async (username: string) => {
|
||||
username = username.trim();
|
||||
if (!username) return;
|
||||
const cacheFile = 'players.cache.json'
|
||||
await Deno.create(cacheFile);
|
||||
await ensureFile(cacheFile);
|
||||
const cache = JSON.parse(await Deno.readTextFile(cacheFile) || '{}');
|
||||
if (!cache[username]) {
|
||||
const req = await fetch('https://playerdb.co/api/player/minecraft/' + username, {
|
||||
|
Reference in New Issue
Block a user