some stuff i dont remember

This commit is contained in:
McMistrzYT 2024-02-04 00:36:28 +01:00
parent 055285a3b0
commit 8145800120
13 changed files with 66 additions and 42 deletions

3
.gitignore vendored
View File

@ -26,4 +26,5 @@ dist-ssr
*.private.*
Out/
Out/
Backup/

View File

@ -1,5 +1,5 @@
import { DataSource } from "typeorm";
import { ENVIRONMENT } from "../Modules/Constants";
import { ENVIRONMENT, SAVED_DATA_PATH } from "../Modules/Constants";
import { Song } from "../Schemas/Song";
import { ForcedCategory } from "../Schemas/ForcedCategory";
import { User } from "../Schemas/User";
@ -7,7 +7,7 @@ import { Rating } from "../Schemas/Rating";
export const DBSource = new DataSource({
type: "better-sqlite3",
database: `Partypack${ENVIRONMENT !== "prod" ? `-${ENVIRONMENT}` : ""}.db`,
database: `${SAVED_DATA_PATH}/Partypack${ENVIRONMENT !== "prod" ? `-${ENVIRONMENT}` : ""}.db`,
synchronize: true,
logging: false,
entities: [

View File

@ -1,6 +1,6 @@
import e from "express"
import fs, { existsSync, mkdirSync } from "fs";
import { BODY_SIZE_LIMIT, COOKIE_SIGN_KEY, DASHBOARD_ROOT, ENDPOINT_AUTHENTICATION_ENABLED, ENDPOINT_AUTH_HEADER, ENDPOINT_AUTH_VALUE, IS_DEBUG, PORT, PROJECT_NAME, SERVER_URL } from "../Modules/Constants";
import { SAVED_DATA_PATH, BODY_SIZE_LIMIT, COOKIE_SIGN_KEY, DASHBOARD_ROOT, ENDPOINT_AUTHENTICATION_ENABLED, ENDPOINT_AUTH_HEADER, ENDPOINT_AUTH_VALUE, IS_DEBUG, PORT, PROJECT_NAME, SERVER_URL } from "../Modules/Constants";
import { Debug, Msg, Warn } from "../Modules/Logger";
import { italic, magenta, red, yellow } from "colorette";
import cookieParser from "cookie-parser";
@ -19,8 +19,8 @@ export const App = e()
.use(e.urlencoded({ limit: BODY_SIZE_LIMIT, extended: false }));
async function Initialize() {
if (!existsSync("./Saved") || !existsSync("./Saved/Songs"))
mkdirSync("./Saved/Songs", { recursive: true });
if (!existsSync(SAVED_DATA_PATH) || !existsSync(`${SAVED_DATA_PATH}/Songs`))
mkdirSync(`${SAVED_DATA_PATH}/Songs`, { recursive: true });
Debug(`The CWD is ${magenta(process.cwd())}.`);

View File

@ -1,6 +1,7 @@
export const ENVIRONMENT = process.env.ENVIRONMENT ?? "dev";
export const IS_DEBUG = ENVIRONMENT.toLowerCase() === "dev" || ENVIRONMENT.toLowerCase() === "stage"; // IS_DEBUG can be used to enable test endpoints, unsafe code and more.
export const SAVED_DATA_PATH = ENVIRONMENT.toLowerCase() === "prod" || ENVIRONMENT.toLowerCase() === "stage" ? "../Saved" : "./Saved";
export const PROJECT_NAME = process.env.PROJECT_NAME ?? "BasedServer"; // Default prefix for the logger module.
export const BODY_SIZE_LIMIT = process.env.BODY_SIZE_LIMIT ?? "10mb"; // Doesn't accept requests with body sizes larger than this value.
export const SERVER_URL = process.env.SERVER_URL ?? "localhost"; // The server's URL. Not used for a lot by default.

View File

@ -9,7 +9,7 @@ import { Debug } from "../Modules/Logger";
import { magenta } from "colorette";
import { fromBuffer } from "file-type";
import { rmSync, writeFileSync, renameSync, readFileSync } from "fs";
import { FULL_SERVER_ROOT, MAX_AMOUNT_OF_DRAFTS_AT_ONCE } from "../Modules/Constants";
import { FULL_SERVER_ROOT, MAX_AMOUNT_OF_DRAFTS_AT_ONCE, SAVED_DATA_PATH } from "../Modules/Constants";
import { UserPermissions } from "../Schemas/User";
cron.schedule("*/2 * * * *", async () => {
@ -84,13 +84,13 @@ App.post("/upload/midi",
if (SongData.Status !== SongStatus.BROKEN && SongData.Status !== SongStatus.DEFAULT && SongData.Status !== SongStatus.DENIED && SongData.Status !== SongStatus.PUBLIC)
return res.status(400).send("You cannot update this song at this moment.");
rmSync(`./Saved/Songs/${req.body.TargetSong}/Data.mid`);
rmSync(`${SAVED_DATA_PATH}/Songs/${req.body.TargetSong}/Data.mid`);
SongData.HasMidi = false;
SongData.IsDraft = true;
await SongData.save();
}
writeFileSync(`./Saved/Songs/${req.body.TargetSong}/Data.mid`, Decoded);
writeFileSync(`${SAVED_DATA_PATH}/Songs/${req.body.TargetSong}/Data.mid`, Decoded);
res.send(`${FULL_SERVER_ROOT}/song/download/${req.body.TargetSong}/midi.mid`);
await SongData.reload();
@ -123,7 +123,7 @@ App.post("/upload/cover",
if (SongData.Status !== SongStatus.BROKEN && SongData.Status !== SongStatus.DEFAULT && SongData.Status !== SongStatus.DENIED && SongData.Status !== SongStatus.PUBLIC)
return res.status(400).send("You cannot update this song at this moment.");
rmSync(`./Saved/Songs/${req.body.TargetSong}/Cover.png`);
rmSync(`${SAVED_DATA_PATH}/Songs/${req.body.TargetSong}/Cover.png`);
SongData.HasCover = false;
SongData.IsDraft = true;
await SongData.save();
@ -158,7 +158,7 @@ App.post("/upload/cover",
SongData.Status = SongData.HasMidi && SongData.HasCover && SongData.HasAudio ? SongStatus.DEFAULT : SongData.Status;
await SongData.save();
writeFileSync(`./Saved/Songs/${req.body.TargetSong}/Cover.png`, Decoded);
writeFileSync(`${SAVED_DATA_PATH}/Songs/${req.body.TargetSong}/Cover.png`, Decoded);
res.send(`${FULL_SERVER_ROOT}/song/download/${req.body.TargetSong}/cover.png`);
});
@ -186,29 +186,30 @@ App.post("/upload/audio",
if (SongData.Status !== SongStatus.BROKEN && SongData.Status !== SongStatus.DEFAULT && SongData.Status !== SongStatus.DENIED && SongData.Status !== SongStatus.PUBLIC)
return res.status(400).send("You cannot update this song at this moment.");
rmSync(`./Saved/Songs/${req.body.TargetSong}/Chunks`, { recursive: true });
rmSync(`${SAVED_DATA_PATH}/Songs/${req.body.TargetSong}/Chunks`, { recursive: true });
SongData.HasAudio = false;
SongData.IsDraft = true;
SongData.Status = SongStatus.PROCESSING;
await SongData.save();
}
await writeFileSync(`./Saved/Songs/${req.body.TargetSong}/Audio.${ext}`, Decoded);
await writeFileSync(`${SAVED_DATA_PATH}/Songs/${req.body.TargetSong}/Audio.${ext}`, Decoded);
ffmpeg()
.input(`./Saved/Songs/${req.body.TargetSong}/Audio.${ext}`)
.input(`${SAVED_DATA_PATH}/Songs/${req.body.TargetSong}/Audio.${ext}`)
.audioCodec("libopus")
.outputOptions([
"-use_timeline 1",
"-f dash"
])
.output(`./Saved/Songs/${req.body.TargetSong}/Chunks/Manifest.mpd`)
.output(`${SAVED_DATA_PATH}/Songs/${req.body.TargetSong}/Chunks/Manifest.mpd`)
.on("start", cl => Debug(`ffmpeg running with ${magenta(cl)}`))
.on("end", async () => {
Debug("Ffmpeg finished running");
rmSync(`./Saved/Songs/${req.body.TargetSong}/Audio.${ext}`);
rmSync(`${SAVED_DATA_PATH}/Songs/${req.body.TargetSong}/Audio.${ext}`);
renameSync(`./Saved/Songs/${req.body.TargetSong}/Chunks/Manifest.mpd`, `./Saved/Songs/${req.body.TargetSong}/Manifest.mpd`);
renameSync(`${SAVED_DATA_PATH}/Songs/${req.body.TargetSong}/Chunks/Manifest.mpd`, `${SAVED_DATA_PATH}/Songs/${req.body.TargetSong}/Manifest.mpd`);
// i love creating thread-safe code that always works! (never gonna error trust me)
writeFileSync(`./Saved/Songs/${req.body.TargetSong}/Manifest.mpd`, readFileSync(`./Saved/Songs/${req.body.TargetSong}/Manifest.mpd`).toString().replace(/<ProgramInformation>[\w\d\r\n\t]*<\/ProgramInformation>/i, "<BaseURL>{BASEURL}</BaseURL>"));
writeFileSync(`${SAVED_DATA_PATH}/Songs/${req.body.TargetSong}/Manifest.mpd`, readFileSync(`${SAVED_DATA_PATH}/Songs/${req.body.TargetSong}/Manifest.mpd`).toString().replace(/<ProgramInformation>[\w\d\r\n\t]*<\/ProgramInformation>/i, "<BaseURL>{BASEURL}</BaseURL>"));
await SongData.reload();
SongData.HasAudio = true;
@ -218,7 +219,7 @@ App.post("/upload/audio",
console.error(e);
console.log(stdout);
console.error(stderr);
rmSync(`./Saved/Songs/${req.body.TargetSong}/Audio.${ext}`);
rmSync(`${SAVED_DATA_PATH}/Songs/${req.body.TargetSong}/Audio.${ext}`);
await SongData.reload();
SongData.Status = SongStatus.BROKEN;

View File

@ -1,5 +1,5 @@
import { BaseEntity, BeforeInsert, BeforeRemove, Column, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm";
import { FULL_SERVER_ROOT } from "../Modules/Constants";
import { FULL_SERVER_ROOT, SAVED_DATA_PATH } from "../Modules/Constants";
import { Rating } from "./Rating";
import { existsSync, mkdirSync, rmSync } from "fs";
import { v4 } from "uuid";
@ -102,7 +102,7 @@ export class Song extends BaseEntity {
@BeforeInsert()
Setup() {
this.ID = v4();
this.Directory = `./Saved/Songs/${this.ID}`;
this.Directory = `${SAVED_DATA_PATH}/Songs/${this.ID}`;
if (!existsSync(join(this.Directory, "Chunks")))
mkdirSync(join(this.Directory, "Chunks"), { recursive: true });

View File

@ -15,6 +15,15 @@ export class User extends BaseEntity {
@PrimaryColumn()
ID: string;
@Column({ default: "unknown" })
Username: string;
@Column({ default: "Unknown" })
DisplayName: string;
@Column({ nullable: true })
ProfilePictureURL?: string;
@Column({ type: "simple-json" })
Library: { SongID: string, Overriding: string }[];

View File

@ -6,9 +6,7 @@
<link rel="icon" type="image/png" href="/public/favicon.webp" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&display=swap"
rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&display=swap" rel="stylesheet">
<link href="https://unpkg.com/@primer/css/dist/primer.css" rel="stylesheet" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta content="Partypack - #1 Festival Modding Tool" property="og:title" />

View File

@ -7,19 +7,16 @@
"dev": "vite",
"build:prod": "vite build",
"build:stage": "vite build --mode staging",
"win:create:prod": "mkdir \"./Out\" && npm run build:prod && move \"./dist\" \"./Out/dist\" && cd \"Server\" && tsc && cd .. && copy \"./Server/.env.prod\" \"./Out/.env\" && copy \"./Server/package.json\" \"./Out/package.json\" && copy \"./Server/package-lock.json\" \"./Out/package-lock.json\"",
"win:publish:prod": "npm run win:create:prod && ssh partypack \"cd /home/PartypackProd; rm -rf ./Out\" && scp -r \"./Out\" partypack:/home/PartypackProd && ssh partypack \"cd /home/PartypackProd/Out && npm i && pm2 restart PartypackProd --update-env\" && rmdir \"./Out\"",
"win:create:stage": "mkdir \"./Out\" && npm run build:stage && move \"./dist\" \"./Out/dist\" && cd \"Server\" && tsc && cd .. && copy \"./Server/.env.staging\" \"./Out/.env\" && copy \"./Server/package.json\" \"./Out/package.json\" && copy \"./Server/package-lock.json\" \"./Out/package-lock.json\"",
"win:create:prod": "mkdir \"./Out\" ; vite build ; move \"./dist\" \"./Out/dist\" ; cd \"Server\" ; tsc ; cd .. ; copy \"./Server/.env.prod\" \"./Out/.env\" ; copy \"./Server/package.json\" \"./Out/package.json\" ; copy \"./Server/package-lock.json\" \"./Out/package-lock.json\"",
"win:publish:prod": "npm run win:create:prod ; ssh partypack \"cd /home/PartypackProd; rm -rf ./Out\" ; scp -r \"./Out\" partypack:/home/PartypackProd ; ssh partypack \"cd /home/PartypackProd/Out && npm i && pm2 restart PartypackProd --update-env\" ; rmdir \"./Out\"",
"win:create:stage": "mkdir \"./Out\" && vite build --mode staging && move \"./dist\" \"./Out/dist\" && cd \"Server\" && tsc && cd .. && copy \"./Server/.env.staging\" \"./Out/.env\" && copy \"./Server/package.json\" \"./Out/package.json\" && copy \"./Server/package-lock.json\" \"./Out/package-lock.json\"",
"win:publish:stage": "npm run win:create:stage && ssh partypack \"cd /home/PartypackStage; rm -rf ./Out\" && scp -r ./Out partypack:/home/PartypackStage && ssh partypack \"cd /home/PartypackStage/Out && npm i && pm2 restart PartypackStage --update-env\" && rmdir \"./Out\"",
"create:prod": "mkdir ./Out && npm run build:prod && mv ./dist ./Out/dist && cd Server && tsc && cd .. && cp ./Server/.env.prod ./Out/.env && cp ./Server/package.json ./Out && cp ./Server/package-lock.json ./Out",
"publish:prod": "npm run create:prod && ssh partypack \"cd /home/PartypackProd; rm -rf ./Out\" && scp -r ./Out partypack:/home/PartypackProd && ssh partypack \"cd /home/PartypackProd/Out && npm i && pm2 restart PartypackProd --update-env\" && rm -rf ./Out",
"create:stage": "mkdir ./Out && npm run build:stage && mv ./dist ./Out/dist && cd Server && tsc && cd .. && cp ./Server/.env.staging ./Out/.env && cp ./Server/package.json ./Out && cp ./Server/package-lock.json ./Out",
"publish:stage": "npm run create:stage && ssh partypack \"cd /home/PartypackStage; rm -rf ./Out\" && scp -r ./Out partypack:/home/PartypackStage && ssh partypack \"cd /home/PartypackStage/Out && npm i && pm2 restart PartypackStage --update-env\" && rm -rf ./Out",
"backup:prod": "scp -r partypack:/home/PartypackProd/Out/Saved ./Backup/Prod/ && scp partypack:/home/PartypackProd/Out/Partypack-prod.db* ./Backup/Prod/",
"backup:stage": "scp -r partypack:/home/PartypackStage/Out/Saved ./Backup/Stage/ && scp partypack:/home/PartypackStage/Out/Partypack-stage.db* ./Backup/Stage/",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview",
"dev:all": "start cmd.exe /k \"cd ./Server && npm run dev:watch\" && vite"

View File

@ -2,7 +2,7 @@ import { Avatar, Box, Header } from "@primer/react";
import { SignInIcon } from "@primer/octicons-react"
import { useCookies } from "react-cookie";
import { useNavigate } from "react-router-dom";
import { useContext, useEffect, useState } from "react";
import { useContext, useEffect } from "react";
import { SiteContext, UserDetailInterface } from "../utils/State";
import { toast } from "react-toastify";
import { Buffer } from "buffer/";
@ -39,7 +39,7 @@ export function SiteHeader() {
<Header.Item full sx={{ cursor: "pointer" }} onClick={() => navigate("/faq")}>FAQ</Header.Item>
<Header.Item full sx={{ cursor: "pointer" }} onClick={() => window.open("https://discord.gg/KaxknAbqDS")}>Discord</Header.Item>
<Header.Item full sx={{ cursor: "pointer", color: "accent.emphasis" }} onClick={() => navigate("/download")}>Download</Header.Item>
{ state.UserDetails?.IsAdmin ? <Header.Item full onClick={() => navigate("/admin")} sx={{ cursor: "pointer", color: "danger.emphasis" }}>Admin</Header.Item> : <></> }
{ state.UserDetails?.IsAdmin ? <Header.Item onClick={() => navigate("/admin")} sx={{ cursor: "pointer", color: "danger.emphasis" }}>Admin</Header.Item> : <></> }
{
cookies["Token"] && state.UserDetails ?
<Header.Item sx={{ mr: 0, cursor: "pointer" }} onClick={() => navigate("/profile")}><Avatar src={state.UserDetails.Avatar} size={25} alt={`${state.UserDetails.GlobalName} (@${state.UserDetails.Username})`}/></Header.Item> :

View File

@ -7,10 +7,14 @@
.songCategory {
display: inline-flex;
flex: none;
overflow-x: auto;
overflow-y: hidden;
gap: 10px;
width: 100%;
overflow-y: hidden;
overflow-x: auto;
}
.songCategory > * {
flex-shrink: 0;
}
#__primerPortalRoot__ > div {

View File

@ -24,10 +24,21 @@ export function AdminTrackList() {
<Heading>[ADMIN] All tracks <Button sx={{ marginBottom: 2 }} onClick={() => navigate("/submissions")}>Create</Button></Heading>
<Box className="songCategory">
{
tracks.map(x => {
tracks.map((x, i) => {
return <Song data={x}>
<Button sx={{ width: "100%", marginBottom: 1 }}>View Details</Button>
<Button sx={{ width: "100%" }} variant="danger">Disable</Button>
<Button sx={{ width: "100%" }} variant="danger" onClick={async () => {
const Res = await axios.post("/api/drafts/delete", { TargetSong: x.ID });
if (Res.status === 200)
{
tracks.splice(i, 1);
setTracks([
...tracks,
])
}
toast(Res.data, { type: Res.status === 200 ? "success" : "error" });
}}>Delete</Button>
</Song>
})
}

View File

@ -1,11 +1,13 @@
import { Box, Text } from "@primer/react";
import { Box, Heading, Text } from "@primer/react";
export function Home() {
return (
<>
<Box>
<Text>online test 2 please kill me thanks</Text>
<Text>CLICK THE LOGIN ICON ON THE TOP RIGHT</Text>
<Heading>PARTYPACK - Placeholder Place Logo Here</Heading>
<Text>Welcome to Partypack! blah blah someone please make this text for me im way too lazy to do allat</Text>
<Heading>Quickstart Guide</Heading>
<Text>1. Kill yourself<br />2. Do it again</Text>
</Box>
</>
)