diff --git a/routes/mods/index.tsx b/routes/mods/index.tsx
new file mode 100644
index 0000000..4095434
--- /dev/null
+++ b/routes/mods/index.tsx
@@ -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 (
+
+
+ Active Mods
+
+
+ {!files.length && (
+
Drop files here to upload
+ )}
+ {files.map((f) => (
+
+
+ {f}
+
+ ))}
+
+
+
+
+ );
+}
+
+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
;
+};
diff --git a/routes/upload.ts b/routes/upload.ts
new file mode 100644
index 0000000..58681b5
--- /dev/null
+++ b/routes/upload.ts
@@ -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");
+ },
+};
diff --git a/state/serverState.ts b/state/serverState.ts
index 2f9d1c2..cf5ac65 100644
--- a/state/serverState.ts
+++ b/state/serverState.ts
@@ -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",
() => {
diff --git a/static/javaicon.png b/static/javaicon.png
new file mode 100644
index 0000000..4ced60f
Binary files /dev/null and b/static/javaicon.png differ
diff --git a/static/styles/tailwind.css b/static/styles/tailwind.css
index 391543d..5693bb4 100644
--- a/static/styles/tailwind.css
+++ b/static/styles/tailwind.css
@@ -1,2 +1,2 @@
@font-face{font-family:Minecraft;font-style:normal;font-weight:400;src:url(/fonts/minecraft/MinecraftRegular.otf)}@font-face{font-family:Minecraft;font-style:normal;font-weight:700;src:url(/fonts/minecraft/MinecraftBold.otf)}@font-face{font-family:Minecraft;font-style:italic;font-weight:700;src:url(/fonts/minecraft/MinecraftBoldItalic.otf)}@font-face{font-family:Minecraft;font-style:italic;font-weight:400;src:url(/fonts/minecraft/MinecraftItalic.otf)}
-/*! tailwindcss v3.2.4 | MIT License | https://tailwindcss.com*/*,:after,:before{border:0 solid #e5e7eb;box-sizing:border-box}:after,:before{--tw-content:""}html{-webkit-text-size-adjust:100%;font-feature-settings:normal;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4}body{line-height:inherit;margin:0}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{color:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#9ca3af;opacity:1}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{margin-left:auto;margin-right:auto;width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}input,select{--tw-text-opacity:1;border-radius:.75rem;color:rgb(0 0 0/var(--tw-text-opacity));padding:.5rem}.absolute{position:absolute}.relative{position:relative}.bottom-4{bottom:1rem}.left-0{left:0}.-bottom-1{bottom:-.25rem}.right-0{right:0}.col-span-2{grid-column:span 2/span 2}.m-auto{margin:auto}.mx-auto{margin-left:auto;margin-right:auto}.my-6{margin-bottom:1.5rem;margin-top:1.5rem}.my-4{margin-bottom:1rem;margin-top:1rem}.mb-8{margin-bottom:2rem}.ml-auto{margin-left:auto}.mt-8{margin-top:2rem}.mt-4{margin-top:1rem}.block{display:block}.flex{display:flex}.grid{display:grid}.contents{display:contents}.h-\[100vh\]{height:100vh}.h-full{height:100%}.h-\[600px\]{height:600px}.h-20{height:5rem}.h-5{height:1.25rem}.h-16{height:4rem}.max-h-full{max-height:100%}.w-full{width:100%}.w-16{width:4rem}.w-20{width:5rem}.w-5{width:1.25rem}.w-24{width:6rem}.min-w-\[400px\]{min-width:400px}.max-w-screen-md{max-width:768px}.flex-1{flex:1 1 0%}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-rows-2{grid-template-rows:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.gap-4{gap:1rem}.gap-8{gap:2rem}.gap-y-4{row-gap:1rem}.gap-x-16{-moz-column-gap:4rem;column-gap:4rem}.overflow-auto{overflow:auto}.overflow-y-auto{overflow-y:auto}.whitespace-nowrap{white-space:nowrap}.rounded-3xl{border-radius:1.5rem}.rounded-lg{border-radius:.5rem}.rounded-xl{border-radius:.75rem}.rounded-full{border-radius:9999px}.rounded-md{border-radius:.375rem}.border{border-width:1px}.border-2{border-width:2px}.border-4{border-width:4px}.border-r-2{border-right-width:2px}.border-sky{--tw-border-opacity:1;border-color:rgb(49 167 230/var(--tw-border-opacity))}.border-sky-950{--tw-border-opacity:1;border-color:rgb(13 44 68/var(--tw-border-opacity))}.border-licorice-800{--tw-border-opacity:1;border-color:rgb(150 60 151/var(--tw-border-opacity))}.border-sky-800{--tw-border-opacity:1;border-color:rgb(17 82 123/var(--tw-border-opacity))}.border-grape-800{--tw-border-opacity:1;border-color:rgb(109 33 135/var(--tw-border-opacity))}.border-fire-800{--tw-border-opacity:1;border-color:rgb(160 20 20/var(--tw-border-opacity))}.border-wasabi-800{--tw-border-opacity:1;border-color:rgb(79 84 32/var(--tw-border-opacity))}.bg-licorice{--tw-bg-opacity:1;background-color:rgb(22 10 22/var(--tw-bg-opacity))}.bg-smoke-900{--tw-bg-opacity:1;background-color:rgb(57 57 65/var(--tw-bg-opacity))}.bg-grape{--tw-bg-opacity:1;background-color:rgb(64 10 80/var(--tw-bg-opacity))}.bg-smoke-500{--tw-bg-opacity:1;background-color:rgb(115 117 132/var(--tw-bg-opacity))}.bg-smoke-600{--tw-bg-opacity:1;background-color:rgb(93 94 108/var(--tw-bg-opacity))}.bg-sky{--tw-bg-opacity:1;background-color:rgb(49 167 230/var(--tw-bg-opacity))}.bg-fire{--tw-bg-opacity:1;background-color:rgb(230 28 28/var(--tw-bg-opacity))}.bg-wasabi-600{--tw-bg-opacity:1;background-color:rgb(128 134 39/var(--tw-bg-opacity))}.bg-smoke-200{--tw-bg-opacity:1;background-color:rgb(217 217 222/var(--tw-bg-opacity))}.bg-black\/50{background-color:#00000080}.bg-smoke{--tw-bg-opacity:1;background-color:rgb(24 24 27/var(--tw-bg-opacity))}.p-4{padding:1rem}.p-8{padding:2rem}.p-2{padding:.5rem}.p-1{padding:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.py-1{padding-bottom:.25rem;padding-top:.25rem}.text-center{text-align:center}.text-right{text-align:right}.font-pixel{font-family:Minecraft,cursive}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-2xl{font-size:1.5rem;line-height:2rem}.text-lg{font-size:1.125rem}.text-lg,.text-xl{line-height:1.75rem}.text-xl{font-size:1.25rem}.text-6xl{font-size:3.75rem;line-height:1}.text-5xl{font-size:3rem;line-height:1}.font-bold{font-weight:700}.text-sky{--tw-text-opacity:1;color:rgb(49 167 230/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-smoke-800\/30{color:#41414b4d}.underline{text-decoration-line:underline}.opacity-50{opacity:.5}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition-colors{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1)}.loader-ball{animation:color-cycle 3s linear infinite;animation-delay:var(--loader-delay);margin:auto}.loader{animation:spin 5s ease-in-out;animation-direction:alternate;animation-iteration-count:infinite}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(4turn)}}@keyframes color-cycle{0%{--tw-bg-opacity:1;background-color:rgb(230 28 28/var(--tw-bg-opacity))}25%{--tw-bg-opacity:1;background-color:rgb(64 10 80/var(--tw-bg-opacity))}50%{--tw-bg-opacity:1;background-color:rgb(49 167 230/var(--tw-bg-opacity))}75%{--tw-bg-opacity:1;background-color:rgb(128 134 39/var(--tw-bg-opacity))}to{--tw-bg-opacity:1;background-color:rgb(230 28 28/var(--tw-bg-opacity))}}*{font-family:Titillium Web,sans-serif}.even\:bg-black\/10:nth-child(2n){background-color:#0000001a}.hover\:bg-smoke-500:hover{--tw-bg-opacity:1;background-color:rgb(115 117 132/var(--tw-bg-opacity))}.disabled\:opacity-30:disabled{opacity:.3}@media (prefers-color-scheme:dark){.dark\:border-sky-950{--tw-border-opacity:1;border-color:rgb(13 44 68/var(--tw-border-opacity))}.dark\:bg-smoke{--tw-bg-opacity:1;background-color:rgb(24 24 27/var(--tw-bg-opacity))}.dark\:bg-smoke-900{--tw-bg-opacity:1;background-color:rgb(57 57 65/var(--tw-bg-opacity))}.dark\:text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}}
\ No newline at end of file
+/*! tailwindcss v3.2.4 | MIT License | https://tailwindcss.com*/*,:after,:before{border:0 solid #e5e7eb;box-sizing:border-box}:after,:before{--tw-content:""}html{-webkit-text-size-adjust:100%;font-feature-settings:normal;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4}body{line-height:inherit;margin:0}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{color:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#9ca3af;opacity:1}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{margin-left:auto;margin-right:auto;width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}input,select{--tw-text-opacity:1;border-radius:.75rem;color:rgb(0 0 0/var(--tw-text-opacity));padding:.5rem}.absolute{position:absolute}.relative{position:relative}.bottom-4{bottom:1rem}.left-0{left:0}.-bottom-1{bottom:-.25rem}.right-0{right:0}.top-0{top:0}.bottom-0{bottom:0}.-z-10{z-index:-10}.col-span-2{grid-column:span 2/span 2}.m-auto{margin:auto}.mx-auto{margin-left:auto;margin-right:auto}.my-6{margin-bottom:1.5rem;margin-top:1.5rem}.my-4{margin-bottom:1rem;margin-top:1rem}.mb-8{margin-bottom:2rem}.ml-auto{margin-left:auto}.mt-8{margin-top:2rem}.mt-4{margin-top:1rem}.block{display:block}.flex{display:flex}.grid{display:grid}.contents{display:contents}.h-\[100vh\]{height:100vh}.h-full{height:100%}.h-4{height:1rem}.h-\[600px\]{height:600px}.h-20{height:5rem}.h-5{height:1.25rem}.h-16{height:4rem}.h-24{height:6rem}.h-40{height:10rem}.max-h-full{max-height:100%}.min-h-\[100px\]{min-height:100px}.w-full{width:100%}.w-24{width:6rem}.w-20{width:5rem}.w-5{width:1.25rem}.w-16{width:4rem}.min-w-\[400px\]{min-width:400px}.max-w-screen-md{max-width:768px}.flex-1{flex:1 1 0%}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-rows-2{grid-template-rows:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.place-items-center{place-items:center}.items-center{align-items:center}.justify-center{justify-content:center}.gap-4{gap:1rem}.gap-2{gap:.5rem}.gap-8{gap:2rem}.gap-y-4{row-gap:1rem}.gap-x-16{-moz-column-gap:4rem;column-gap:4rem}.place-self-center{place-self:center}.overflow-auto{overflow:auto}.overflow-y-auto{overflow-y:auto}.whitespace-nowrap{white-space:nowrap}.rounded-3xl{border-radius:1.5rem}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.rounded-full{border-radius:9999px}.border{border-width:1px}.border-2{border-width:2px}.border-4{border-width:4px}.border-r-2{border-right-width:2px}.border-sky{--tw-border-opacity:1;border-color:rgb(49 167 230/var(--tw-border-opacity))}.border-sky-950{--tw-border-opacity:1;border-color:rgb(13 44 68/var(--tw-border-opacity))}.border-licorice-800{--tw-border-opacity:1;border-color:rgb(150 60 151/var(--tw-border-opacity))}.border-sky-800{--tw-border-opacity:1;border-color:rgb(17 82 123/var(--tw-border-opacity))}.border-grape-800{--tw-border-opacity:1;border-color:rgb(109 33 135/var(--tw-border-opacity))}.border-fire-800{--tw-border-opacity:1;border-color:rgb(160 20 20/var(--tw-border-opacity))}.border-wasabi-800{--tw-border-opacity:1;border-color:rgb(79 84 32/var(--tw-border-opacity))}.bg-licorice{--tw-bg-opacity:1;background-color:rgb(22 10 22/var(--tw-bg-opacity))}.bg-smoke-900{--tw-bg-opacity:1;background-color:rgb(57 57 65/var(--tw-bg-opacity))}.bg-grape{--tw-bg-opacity:1;background-color:rgb(64 10 80/var(--tw-bg-opacity))}.bg-smoke-500{--tw-bg-opacity:1;background-color:rgb(115 117 132/var(--tw-bg-opacity))}.bg-black\/50{background-color:#00000080}.bg-smoke{--tw-bg-opacity:1;background-color:rgb(24 24 27/var(--tw-bg-opacity))}.bg-smoke-600{--tw-bg-opacity:1;background-color:rgb(93 94 108/var(--tw-bg-opacity))}.bg-sky{--tw-bg-opacity:1;background-color:rgb(49 167 230/var(--tw-bg-opacity))}.bg-fire{--tw-bg-opacity:1;background-color:rgb(230 28 28/var(--tw-bg-opacity))}.bg-wasabi-600{--tw-bg-opacity:1;background-color:rgb(128 134 39/var(--tw-bg-opacity))}.bg-smoke-200{--tw-bg-opacity:1;background-color:rgb(217 217 222/var(--tw-bg-opacity))}.bg-smoke-600\/20{background-color:#5d5e6c33}.p-4{padding:1rem}.p-8{padding:2rem}.p-2{padding:.5rem}.p-1{padding:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.py-1{padding-bottom:.25rem;padding-top:.25rem}.text-center{text-align:center}.text-right{text-align:right}.font-pixel{font-family:Minecraft,cursive}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-2xl{font-size:1.5rem;line-height:2rem}.text-lg{font-size:1.125rem}.text-lg,.text-xl{line-height:1.75rem}.text-xl{font-size:1.25rem}.text-6xl{font-size:3.75rem;line-height:1}.text-5xl{font-size:3rem;line-height:1}.font-bold{font-weight:700}.text-sky{--tw-text-opacity:1;color:rgb(49 167 230/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-smoke-800\/30{color:#41414b4d}.underline{text-decoration-line:underline}.opacity-50{opacity:.5}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition-colors{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1)}.loader-ball{animation:color-cycle 3s linear infinite;animation-delay:var(--loader-delay);margin:auto}.loader{animation:spin 5s ease-in-out;animation-direction:alternate;animation-iteration-count:infinite}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(4turn)}}@keyframes color-cycle{0%{--tw-bg-opacity:1;background-color:rgb(230 28 28/var(--tw-bg-opacity))}25%{--tw-bg-opacity:1;background-color:rgb(64 10 80/var(--tw-bg-opacity))}50%{--tw-bg-opacity:1;background-color:rgb(49 167 230/var(--tw-bg-opacity))}75%{--tw-bg-opacity:1;background-color:rgb(128 134 39/var(--tw-bg-opacity))}to{--tw-bg-opacity:1;background-color:rgb(230 28 28/var(--tw-bg-opacity))}}*{font-family:Titillium Web,sans-serif}.even\:bg-black\/10:nth-child(2n){background-color:#0000001a}.hover\:bg-smoke-500:hover{--tw-bg-opacity:1;background-color:rgb(115 117 132/var(--tw-bg-opacity))}.disabled\:opacity-30:disabled{opacity:.3}@media (prefers-color-scheme:dark){.dark\:border-sky-950{--tw-border-opacity:1;border-color:rgb(13 44 68/var(--tw-border-opacity))}.dark\:bg-smoke{--tw-bg-opacity:1;background-color:rgb(24 24 27/var(--tw-bg-opacity))}.dark\:bg-smoke-900{--tw-bg-opacity:1;background-color:rgb(57 57 65/var(--tw-bg-opacity))}.dark\:text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}}@media (min-width:1024px){.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}
\ No newline at end of file
diff --git a/test.json b/test.json
new file mode 100644
index 0000000..f733b38
--- /dev/null
+++ b/test.json
@@ -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
+}
diff --git a/types/mcgrizzconf.ts b/types/mcgrizzconf.ts
index e2ac25b..450d66a 100644
--- a/types/mcgrizzconf.ts
+++ b/types/mcgrizzconf.ts
@@ -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
-}
\ No newline at end of file
+ loader: Loader;
+ version: string;
+ mods?: {
+ source: "modrinth";
+ details: ModrinthProject;
+ jarName?: string;
+ }[];
+};
diff --git a/util/EULA.ts b/util/EULA.ts
index 824d954..589565b 100644
--- a/util/EULA.ts
+++ b/util/EULA.ts
@@ -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`);
diff --git a/util/confFile.ts b/util/confFile.ts
index cb4e11d..427d35f 100644
--- a/util/confFile.ts
+++ b/util/confFile.ts
@@ -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
) {
- const conf = {...getConfFile(), newConf};
+ if (IS_BROWSER) return;
+ const conf = {...getConfFile(), ...newConf};
await Deno.writeTextFile(confPath, JSON.stringify(conf, null, 2));
}
diff --git a/util/download.ts b/util/download.ts
new file mode 100644
index 0000000..7cbffe4
--- /dev/null
+++ b/util/download.ts
@@ -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);
+}
\ No newline at end of file
diff --git a/util/getNavItems.ts b/util/getNavItems.ts
index 87029ae..21639ca 100644
--- a/util/getNavItems.ts
+++ b/util/getNavItems.ts
@@ -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;
}
diff --git a/util/players.ts b/util/players.ts
index 23ce7d3..e060917 100644
--- a/util/players.ts
+++ b/util/players.ts
@@ -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, {