raah
This commit is contained in:
parent
b97048d3fb
commit
017b619766
|
@ -7,8 +7,9 @@ import { RequireAuthentication, ValidateBody } from "../Modules/Middleware";
|
||||||
import { writeFileSync } from "fs";
|
import { writeFileSync } from "fs";
|
||||||
import { ForcedCategory } from "../Schemas/ForcedCategory";
|
import { ForcedCategory } from "../Schemas/ForcedCategory";
|
||||||
import { fromBuffer } from "file-type";
|
import { fromBuffer } from "file-type";
|
||||||
|
import { Debug } from "../Modules/Logger";
|
||||||
|
import { magenta } from "colorette";
|
||||||
import ffmpeg from "fluent-ffmpeg";
|
import ffmpeg from "fluent-ffmpeg";
|
||||||
import exif from "exif-reader";
|
|
||||||
import j from "joi";
|
import j from "joi";
|
||||||
|
|
||||||
const App = Router();
|
const App = Router();
|
||||||
|
@ -75,11 +76,12 @@ async (req, res) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
App.post("/upload/audio",
|
App.post("/upload/audio",
|
||||||
ValidateBody(j.object({
|
RequireAuthentication(),
|
||||||
|
ValidateBody(j.object({
|
||||||
Data: j.string().hex().required(),
|
Data: j.string().hex().required(),
|
||||||
TargetSong: j.string().uuid().required()
|
TargetSong: j.string().uuid().required()
|
||||||
})),
|
})),
|
||||||
async (req, res) => {
|
async (req, res) => {
|
||||||
const Decoded = Buffer.from(req.body.Data, "hex");
|
const Decoded = Buffer.from(req.body.Data, "hex");
|
||||||
const ext = (await fromBuffer(Decoded))!.ext;
|
const ext = (await fromBuffer(Decoded))!.ext;
|
||||||
|
|
||||||
|
@ -89,12 +91,22 @@ async (req, res) => {
|
||||||
if (!await Song.exists({ where: { ID: req.body.TargetSong } }))
|
if (!await Song.exists({ where: { ID: req.body.TargetSong } }))
|
||||||
return res.status(404).send("The song you're trying to upload audio for does not exist.");
|
return res.status(404).send("The song you're trying to upload audio for does not exist.");
|
||||||
|
|
||||||
// TODO: implement checks for this
|
await writeFileSync(`./Saved/Songs/${req.body.TargetSong}/Audio.${ext}`, Decoded);
|
||||||
writeFileSync(`./Saved/Songs/${req.body.TargetSong}/Audio.${ext}`, Decoded);
|
|
||||||
|
|
||||||
ffmpeg()
|
ffmpeg()
|
||||||
.input("")
|
.input(`./Saved/Songs/${req.body.TargetSong}/Audio.${ext}`)
|
||||||
})
|
.outputOptions([
|
||||||
|
"-map 0",
|
||||||
|
"-use_timeline 1",
|
||||||
|
"-f dash"
|
||||||
|
])
|
||||||
|
.output(`./Saved/Songs/${req.body.TargetSong}/Chunks/Manifest.mpd`)
|
||||||
|
.on("start", cl => Debug(`ffmpeg running with ${magenta(cl)}`))
|
||||||
|
.on("end", () => Debug("Ffmpeg finished running"))
|
||||||
|
.on("error", (e, stdout, stderr) => { console.error(e); console.log(stdout); console.error(stderr); })
|
||||||
|
.run();
|
||||||
|
|
||||||
|
res.send("ffmpeg now running on song.");
|
||||||
|
});
|
||||||
|
|
||||||
App.post("/upload/cover",
|
App.post("/upload/cover",
|
||||||
ValidateBody(j.object({
|
ValidateBody(j.object({
|
||||||
|
@ -106,13 +118,13 @@ async (req, res) => {
|
||||||
const ext = (await fromBuffer(Decoded))!.ext;
|
const ext = (await fromBuffer(Decoded))!.ext;
|
||||||
|
|
||||||
if (ext !== "png")
|
if (ext !== "png")
|
||||||
return res.status(404).send("Invalid image file. (supported: png)");
|
return res.status(400).send("Invalid image file. (supported: png)");
|
||||||
|
|
||||||
if (!await Song.exists({ where: { ID: req.body.TargetSong } }))
|
if (!await Song.exists({ where: { ID: req.body.TargetSong } }))
|
||||||
return res.status(404).send("The song you're trying to upload a cover for does not exist.");
|
return res.status(404).send("The song you're trying to upload a cover for does not exist.");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const ImageMetadata = exif(Decoded);
|
/*const ImageMetadata = exif(Decoded);
|
||||||
if (!ImageMetadata.Image?.ImageWidth || !ImageMetadata.Image?.ImageLength)
|
if (!ImageMetadata.Image?.ImageWidth || !ImageMetadata.Image?.ImageLength)
|
||||||
throw new Error("Invalid image file.");
|
throw new Error("Invalid image file.");
|
||||||
|
|
||||||
|
@ -120,7 +132,7 @@ async (req, res) => {
|
||||||
return res.status(400).send("Image must have a 1:1 ratio.");
|
return res.status(400).send("Image must have a 1:1 ratio.");
|
||||||
|
|
||||||
if (ImageMetadata.Image.ImageWidth < 512 || ImageMetadata.Image.ImageWidth > 2048)
|
if (ImageMetadata.Image.ImageWidth < 512 || ImageMetadata.Image.ImageWidth > 2048)
|
||||||
return res.status(400).send("Image cannot be smaller than 512 pixels and larger than 2048 pixels.");
|
return res.status(400).send("Image cannot be smaller than 512 pixels and larger than 2048 pixels.");*/
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
return res.status(400).send("Invalid image file.");
|
return res.status(400).send("Invalid image file.");
|
||||||
|
|
|
@ -9,7 +9,7 @@ App.get("/", async (req, res) => {
|
||||||
const New = {
|
const New = {
|
||||||
ID: "new",
|
ID: "new",
|
||||||
Header: "Recently added",
|
Header: "Recently added",
|
||||||
Songs: (await Song.find({ take: 10, order: { CreationDate: "DESC" } })).map(x => x.Package()),
|
Songs: (await Song.find({ where: { IsDraft: false }, take: 10, order: { CreationDate: "DESC" } })).map(x => x.Package()),
|
||||||
Priority: 100,
|
Priority: 100,
|
||||||
Custom: false
|
Custom: false
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,15 +3,23 @@ import { existsSync, readFileSync } from "fs";
|
||||||
import { FULL_SERVER_ROOT } from "../Modules/Constants";
|
import { FULL_SERVER_ROOT } from "../Modules/Constants";
|
||||||
import { CreateBlurl } from "../Modules/BLURL";
|
import { CreateBlurl } from "../Modules/BLURL";
|
||||||
import { Song } from "../Schemas/Song";
|
import { Song } from "../Schemas/Song";
|
||||||
|
import { RequireAuthentication } from "../Modules/Middleware";
|
||||||
|
|
||||||
const App = Router();
|
const App = Router();
|
||||||
|
|
||||||
App.get("/song/download/:InternalID/:File", async (req, res) => {
|
App.get("/song/download/:InternalID/:File",
|
||||||
|
RequireAuthentication(),
|
||||||
|
async (req, res) => {
|
||||||
//const Song = AvailableFestivalSongs.find(x => x.UUID === req.params.SongUUID);
|
//const Song = AvailableFestivalSongs.find(x => x.UUID === req.params.SongUUID);
|
||||||
const SongData = await Song.findOne({ where: { ID: req.params.InternalID } });
|
const SongData = await Song.findOne({ where: { ID: req.params.InternalID }, relations: { Author: true } });
|
||||||
if (!SongData)
|
if (!SongData)
|
||||||
return res.status(404).json({ errorMessage: "Song not found." });
|
return res.status(404).json({ errorMessage: "Song not found." });
|
||||||
|
|
||||||
|
console.log(SongData);
|
||||||
|
|
||||||
|
if (SongData.IsDraft && SongData.Author.ID !== req.user!.ID)
|
||||||
|
return res.status(403).json({ errorMessage: "You cannot use this track, because it's a draft." });
|
||||||
|
|
||||||
const BaseURL = `${FULL_SERVER_ROOT}/song/download/${SongData.ID}/`;
|
const BaseURL = `${FULL_SERVER_ROOT}/song/download/${SongData.ID}/`;
|
||||||
switch (req.params.File.toLowerCase()) {
|
switch (req.params.File.toLowerCase()) {
|
||||||
case "master.blurl":
|
case "master.blurl":
|
||||||
|
@ -64,10 +72,13 @@ App.get("/song/download/:InternalID/:File", async (req, res) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
App.get("/:InternalID", async (req, res, next) => {
|
App.get("/:InternalID", async (req, res, next) => {
|
||||||
const SongData = await Song.findOne({ where: { ID: req.params.InternalID } });
|
const SongData = await Song.findOne({ where: { ID: req.params.InternalID }, relations: { Author: true } });
|
||||||
if (!SongData)
|
if (!SongData)
|
||||||
return next(); // trust me bro
|
return next(); // trust me bro
|
||||||
|
|
||||||
|
if (SongData.IsDraft && SongData.Author.ID !== req.user!.ID)
|
||||||
|
return res.status(403).json({ errorMessage: "You cannot use this track, because it's a draft." });
|
||||||
|
|
||||||
const BaseURL = `${FULL_SERVER_ROOT}/song/download/${SongData.ID}/`;
|
const BaseURL = `${FULL_SERVER_ROOT}/song/download/${SongData.ID}/`;
|
||||||
res.set("content-type", "application/json");
|
res.set("content-type", "application/json");
|
||||||
res.json({
|
res.json({
|
||||||
|
|
|
@ -7,8 +7,9 @@ import { Song } from "../Schemas/Song";
|
||||||
import { Debug } from "../Modules/Logger";
|
import { Debug } from "../Modules/Logger";
|
||||||
import { magenta } from "colorette";
|
import { magenta } from "colorette";
|
||||||
import { fromBuffer } from "file-type";
|
import { fromBuffer } from "file-type";
|
||||||
import { writeFileSync } from "fs";
|
import { rmSync, writeFileSync } from "fs";
|
||||||
import { FULL_SERVER_ROOT } from "../Modules/Constants";
|
import { FULL_SERVER_ROOT } from "../Modules/Constants";
|
||||||
|
import { UserPermissions } from "../Schemas/User";
|
||||||
|
|
||||||
const App = Router();
|
const App = Router();
|
||||||
|
|
||||||
|
@ -32,7 +33,8 @@ App.post("/create",
|
||||||
async (req, res) => {
|
async (req, res) => {
|
||||||
const SongData = await Song.create({
|
const SongData = await Song.create({
|
||||||
...req.body,
|
...req.body,
|
||||||
IsDraft: true
|
IsDraft: true,
|
||||||
|
Author: req.user!
|
||||||
}).save();
|
}).save();
|
||||||
|
|
||||||
Debug(`New draft created by ${magenta(req.user!.ID!)} as ${magenta(`${SongData.ArtistName} - ${SongData.Name}`)}`)
|
Debug(`New draft created by ${magenta(req.user!.ID!)} as ${magenta(`${SongData.ArtistName} - ${SongData.Name}`)}`)
|
||||||
|
@ -71,11 +73,15 @@ App.post("/upload/cover",
|
||||||
if (ext !== "png")
|
if (ext !== "png")
|
||||||
return res.status(404).send("Invalid image file. (supported: png)");
|
return res.status(404).send("Invalid image file. (supported: png)");
|
||||||
|
|
||||||
if (!await Song.exists({ where: { ID: req.body.TargetSong } }))
|
const SongData = await Song.findOne({ where: { ID: req.body.TargetSong }, relations: { Author: true } })
|
||||||
|
if (!SongData)
|
||||||
return res.status(404).send("The song you're trying to upload a cover for does not exist.");
|
return res.status(404).send("The song you're trying to upload a cover for does not exist.");
|
||||||
|
|
||||||
|
if (req.user!.PermissionLevel! < UserPermissions.Administrator && SongData.Author.ID !== req.user!.ID)
|
||||||
|
return res.status(403).send("You don't have permission to upload to this song.");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const ImageMetadata = exif(Decoded);
|
/*const ImageMetadata = exif(Decoded);
|
||||||
if (!ImageMetadata.Image?.ImageWidth || !ImageMetadata.Image?.ImageLength)
|
if (!ImageMetadata.Image?.ImageWidth || !ImageMetadata.Image?.ImageLength)
|
||||||
throw new Error("Invalid image file.");
|
throw new Error("Invalid image file.");
|
||||||
|
|
||||||
|
@ -83,7 +89,7 @@ App.post("/upload/cover",
|
||||||
return res.status(400).send("Image must have a 1:1 ratio.");
|
return res.status(400).send("Image must have a 1:1 ratio.");
|
||||||
|
|
||||||
if (ImageMetadata.Image.ImageWidth < 512 || ImageMetadata.Image.ImageWidth > 2048)
|
if (ImageMetadata.Image.ImageWidth < 512 || ImageMetadata.Image.ImageWidth > 2048)
|
||||||
return res.status(400).send("Image cannot be smaller than 512 pixels and larger than 2048 pixels.");
|
return res.status(400).send("Image cannot be smaller than 512 pixels and larger than 2048 pixels.");*/
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
return res.status(400).send("Invalid image file.");
|
return res.status(400).send("Invalid image file.");
|
||||||
|
@ -112,19 +118,23 @@ App.post("/upload/audio",
|
||||||
await writeFileSync(`./Saved/Songs/${req.body.TargetSong}/Audio.${ext}`, Decoded);
|
await writeFileSync(`./Saved/Songs/${req.body.TargetSong}/Audio.${ext}`, Decoded);
|
||||||
ffmpeg()
|
ffmpeg()
|
||||||
.input(`./Saved/Songs/${req.body.TargetSong}/Audio.${ext}`)
|
.input(`./Saved/Songs/${req.body.TargetSong}/Audio.${ext}`)
|
||||||
.inputOptions(["-re"])
|
|
||||||
.outputOptions([
|
.outputOptions([
|
||||||
"-map 0",
|
"-map 0",
|
||||||
"-c:a aac",
|
|
||||||
"-ar:a:0 48000",
|
|
||||||
"-use_timeline 1",
|
"-use_timeline 1",
|
||||||
"-adaptation_sets \"id=0,streams=a\"",
|
|
||||||
"-f dash"
|
"-f dash"
|
||||||
])
|
])
|
||||||
.output(`./Saved/Songs/${req.body.TargetSong}/Chunks/Manifest.mpd`)
|
.output(`./Saved/Songs/${req.body.TargetSong}/Chunks/Manifest.mpd`)
|
||||||
.on("start", cl => Debug(`ffmpeg running with ${magenta(cl)}`))
|
.on("start", cl => Debug(`ffmpeg running with ${magenta(cl)}`))
|
||||||
.on("end", () => Debug("Ffmpeg finished running"))
|
.on("end", () => {
|
||||||
.on("error", (e, stdout, stderr) => { console.error(e); console.log(stdout); console.error(stderr); })
|
Debug("Ffmpeg finished running");
|
||||||
|
rmSync(`./Saved/Songs/${req.body.TargetSong}/Audio.${ext}`);
|
||||||
|
})
|
||||||
|
.on("error", (e, stdout, stderr) => {
|
||||||
|
console.error(e);
|
||||||
|
console.log(stdout);
|
||||||
|
console.error(stderr);
|
||||||
|
rmSync(`./Saved/Songs/${req.body.TargetSong}/Audio.${ext}`);
|
||||||
|
})
|
||||||
.run();
|
.run();
|
||||||
|
|
||||||
res.send("ffmpeg now running on song.");
|
res.send("ffmpeg now running on song.");
|
||||||
|
|
|
@ -6,9 +6,10 @@ import j from "joi";
|
||||||
|
|
||||||
const App = Router();
|
const App = Router();
|
||||||
|
|
||||||
App.get("/me", RequireAuthentication({ BookmarkedSongs: true }), (req, res) => {
|
App.get("/me", RequireAuthentication({ BookmarkedSongs: true, CreatedTracks: true }), (req, res) => {
|
||||||
res.json({
|
res.json({
|
||||||
Bookmarks: req.user?.BookmarkedSongs.map(x => x.Package()),
|
Bookmarks: req.user?.BookmarkedSongs.map(x => x.Package()),
|
||||||
|
Created: req.user?.CreatedTracks.map(x => x.Package()),
|
||||||
Library: req.user?.Library
|
Library: req.user?.Library
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -60,10 +61,13 @@ async (req, res) => {
|
||||||
if (req.user?.BookmarkedSongs.findIndex(x => x.ID.toLowerCase() === req.body.SongID.toLowerCase()) !== -1)
|
if (req.user?.BookmarkedSongs.findIndex(x => x.ID.toLowerCase() === req.body.SongID.toLowerCase()) !== -1)
|
||||||
return res.status(400).json({ errorMessage: "You're already subscribed to this song." });
|
return res.status(400).json({ errorMessage: "You're already subscribed to this song." });
|
||||||
|
|
||||||
const SongData = await Song.findOne({ where: { ID: req.body.SongID } });
|
const SongData = await Song.findOne({ where: { ID: req.body.SongID }, relations: { Author: true } });
|
||||||
if (!SongData)
|
if (!SongData)
|
||||||
return res.status(404).json({ errorMessage: "Provided song doesn't exist." });
|
return res.status(404).json({ errorMessage: "Provided song doesn't exist." });
|
||||||
|
|
||||||
|
if (SongData.IsDraft && SongData.Author.ID !== req.user.ID)
|
||||||
|
return res.status(403).json({ errorMessage: "You cannot subscribe to this track, because it's a draft." });
|
||||||
|
|
||||||
req.user?.BookmarkedSongs.push(SongData);
|
req.user?.BookmarkedSongs.push(SongData);
|
||||||
req.user?.save();
|
req.user?.save();
|
||||||
|
|
||||||
|
@ -86,10 +90,15 @@ async (req, res) => {
|
||||||
res.json(req.user?.BookmarkedSongs.map(x => x.Package()));
|
res.json(req.user?.BookmarkedSongs.map(x => x.Package()));
|
||||||
})
|
})
|
||||||
|
|
||||||
App.get("/song/data/:InternalID", async (req, res) => {
|
App.get("/song/data/:InternalID",
|
||||||
const SongData = await Song.findOne({ where: { ID: req.params.InternalID } });
|
RequireAuthentication(),
|
||||||
|
async (req, res) => {
|
||||||
|
const SongData = await Song.findOne({ where: { ID: req.params.InternalID }, relations: { Author: true } });
|
||||||
if (!SongData)
|
if (!SongData)
|
||||||
return res.status(404).json({ errorMessage: "Song not found." });
|
return res.status(404).json({ errorMessage: "Provided song doesn't exist." });
|
||||||
|
|
||||||
|
if (SongData.IsDraft && SongData.Author.ID !== req.user!.ID)
|
||||||
|
return res.status(403).json({ errorMessage: "You cannot use this track, because it's a draft." });
|
||||||
|
|
||||||
res.json(SongData.Package());
|
res.json(SongData.Package());
|
||||||
})
|
})
|
||||||
|
|
|
@ -65,6 +65,9 @@ export class Song extends BaseEntity {
|
||||||
@Column()
|
@Column()
|
||||||
IsDraft: boolean;
|
IsDraft: boolean;
|
||||||
|
|
||||||
|
@Column({ default: false })
|
||||||
|
DraftAwaitingReview: boolean;
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
CreationDate: Date;
|
CreationDate: Date;
|
||||||
|
|
||||||
|
|
14
package.json
14
package.json
|
@ -8,11 +8,17 @@
|
||||||
"build:prod": "vite build",
|
"build:prod": "vite build",
|
||||||
"build:stage": "vite build --mode staging",
|
"build:stage": "vite build --mode staging",
|
||||||
|
|
||||||
"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: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\"",
|
||||||
"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\" && rmdir \"./Out\"",
|
"win: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\" && rmdir \"./Out\"",
|
||||||
|
|
||||||
"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: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\"",
|
||||||
"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\" && rmdir \"./Out\"",
|
"win: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\" && 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",
|
||||||
|
|
||||||
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Box, Text } from "@primer/react";
|
import { Box, Label, Text } from "@primer/react";
|
||||||
import { Divider } from "@primer/react/lib-esm/ActionList/Divider";
|
import { Divider } from "@primer/react/lib-esm/ActionList/Divider";
|
||||||
|
|
||||||
export function Song({ data, children }: { data: any, children?: JSX.Element[] | JSX.Element | string }) {
|
export function Song({ data, children }: { data: any, children?: JSX.Element[] | JSX.Element | string }) {
|
||||||
|
@ -8,6 +8,9 @@ export function Song({ data, children }: { data: any, children?: JSX.Element[] |
|
||||||
<center>
|
<center>
|
||||||
<Text sx={{ display: "block", textOverflow: "ellipsis", overflow: "hidden", whiteSpace: "nowrap" }}>{data.ArtistName}</Text>
|
<Text sx={{ display: "block", textOverflow: "ellipsis", overflow: "hidden", whiteSpace: "nowrap" }}>{data.ArtistName}</Text>
|
||||||
<Text sx={{ display: "block", textOverflow: "ellipsis", overflow: "hidden", whiteSpace: "nowrap" }}><b>{data.Name}</b></Text>
|
<Text sx={{ display: "block", textOverflow: "ellipsis", overflow: "hidden", whiteSpace: "nowrap" }}><b>{data.Name}</b></Text>
|
||||||
|
{
|
||||||
|
data.IsDraft ? <Label variant="danger">Draft - not published</Label> : <></>
|
||||||
|
}
|
||||||
{
|
{
|
||||||
children ? <Divider /> : <></>
|
children ? <Divider /> : <></>
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ export function Profile() {
|
||||||
const [isActivateDialogOpen, setIsActivateDialogOpen] = useState<boolean>(false);
|
const [isActivateDialogOpen, setIsActivateDialogOpen] = useState<boolean>(false);
|
||||||
const [librarySongs, setLibrarySongs] = useState<unknown[]>([]);
|
const [librarySongs, setLibrarySongs] = useState<unknown[]>([]);
|
||||||
const [bookmarkedSongs, setBookmarkedSongs] = useState<unknown[]>([]);
|
const [bookmarkedSongs, setBookmarkedSongs] = useState<unknown[]>([]);
|
||||||
|
const [draftsSongs, setDraftsSongs] = useState<unknown[]>([]);
|
||||||
const [availableOverrides, setAvailableOverrides] = useState<{ Name: string, Template: string }[]>([]);
|
const [availableOverrides, setAvailableOverrides] = useState<{ Name: string, Template: string }[]>([]);
|
||||||
const [overriding, setOverriding] = useState<unknown>({});
|
const [overriding, setOverriding] = useState<unknown>({});
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
@ -28,9 +29,9 @@ export function Profile() {
|
||||||
return toast("An error has occured while getting your library!", { type: "error" });
|
return toast("An error has occured while getting your library!", { type: "error" });
|
||||||
|
|
||||||
const LibSongs = (await Promise.all(Data.data.Library.map((x: { SongID: string; }) => axios.get(`/api/library/song/data/${x.SongID}`)))).map(x => { return { ...x.data, Override: Data.data.Library.find((y: { SongID: string; }) => y.SongID === x.data.ID).Overriding } });
|
const LibSongs = (await Promise.all(Data.data.Library.map((x: { SongID: string; }) => axios.get(`/api/library/song/data/${x.SongID}`)))).map(x => { return { ...x.data, Override: Data.data.Library.find((y: { SongID: string; }) => y.SongID === x.data.ID).Overriding } });
|
||||||
const BookSongs = (await Promise.all(Data.data.Bookmarks.map((x: { ID: string; }) => axios.get(`/api/library/song/data/${x.ID}`)))).map(x => x.data);
|
|
||||||
setLibrarySongs(LibSongs);
|
setLibrarySongs(LibSongs);
|
||||||
setBookmarkedSongs(BookSongs);
|
setBookmarkedSongs(Data.data.Bookmarks);
|
||||||
|
setDraftsSongs(Data.data.Created);
|
||||||
setAvailableOverrides(Overrides.data);
|
setAvailableOverrides(Overrides.data);
|
||||||
})();
|
})();
|
||||||
}, []);
|
}, []);
|
||||||
|
@ -126,6 +127,28 @@ export function Profile() {
|
||||||
: <Text>You have no bookmarked songs.</Text>
|
: <Text>You have no bookmarked songs.</Text>
|
||||||
}
|
}
|
||||||
</Box>
|
</Box>
|
||||||
|
<Heading sx={{ marginTop: 2, marginBottom: 2 }}>My Drafts & Published Songs</Heading>
|
||||||
|
<Box className="songCategory">
|
||||||
|
{
|
||||||
|
draftsSongs.length >= 1 ?
|
||||||
|
draftsSongs.map(x => {
|
||||||
|
return <Song data={x}>
|
||||||
|
<Button sx={{ width: "100%", marginBottom: 1 }} variant="primary" onClick={() => { setIsActivateDialogOpen(true); setOverriding(x) }} disabled={librarySongs.findIndex(y => y.ID === x.ID) !== -1}>Add to Active</Button>
|
||||||
|
<Button sx={{ width: "100%", marginBottom: 1 }}>Publish</Button>
|
||||||
|
<Button sx={{ width: "100%" }} variant="danger" onClick={async () => {
|
||||||
|
const Res = await axios.post("/api/drafts/delete", { SongID: x.ID });
|
||||||
|
if (Res.status === 200) {
|
||||||
|
draftsSongs.splice(draftsSongs.findIndex(y => y.ID === x.ID), 1);
|
||||||
|
setDraftsSongs([...draftsSongs]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
toast(Res.data.errorMessage, { type: "error" })
|
||||||
|
}}>Unsubscribe</Button>
|
||||||
|
</Song>;
|
||||||
|
})
|
||||||
|
: <Text>You have no bookmarked songs.</Text>
|
||||||
|
}
|
||||||
|
</Box>
|
||||||
</Box> :
|
</Box> :
|
||||||
<>
|
<>
|
||||||
<Text>You are not logged in.<br />Log in using the button in the top right.</Text>
|
<Text>You are not logged in.<br />Log in using the button in the top right.</Text>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user