2024-01-28 11:07:10 +01:00
|
|
|
import { Router } from "express";
|
|
|
|
import { RequireAuthentication, ValidateBody } from "../Modules/Middleware";
|
2024-01-31 00:27:53 +01:00
|
|
|
import { Song, SongStatus } from "../Schemas/Song";
|
2024-01-28 11:07:10 +01:00
|
|
|
import { OriginalSparks } from "../Modules/FNUtil";
|
|
|
|
import j from "joi";
|
2024-01-28 23:36:28 +01:00
|
|
|
import { UserPermissions } from "../Schemas/User";
|
2024-02-03 01:41:24 +01:00
|
|
|
import { AsyncFilter } from "../Modules/Extensions";
|
2024-01-28 11:07:10 +01:00
|
|
|
|
|
|
|
const App = Router();
|
|
|
|
|
2024-01-31 00:27:53 +01:00
|
|
|
App.get("/me", RequireAuthentication({ BookmarkedSongs: true, CreatedTracks: true }), async (req, res) => {
|
|
|
|
const ProcessingTracks = req.user!.CreatedTracks.filter(x => x.Status === SongStatus.PROCESSING);
|
2024-02-03 01:41:24 +01:00
|
|
|
// @ts-expect-error not gonna bother making type
|
|
|
|
const NonExistingActiveTracks = await AsyncFilter(req.user!.Library, async x => !(await Song.exists({ where: { ID: x.SongID } })));
|
|
|
|
|
|
|
|
if (NonExistingActiveTracks.length > 0) {
|
|
|
|
for (const Track of NonExistingActiveTracks) {
|
|
|
|
console.log(Track);
|
|
|
|
// @ts-expect-error again not gonna bother making type
|
|
|
|
req.user!.Library.splice(req.user!.Library.findIndex(x => x.SongID === Track.SongID), 1);
|
|
|
|
}
|
|
|
|
await req.user!.save();
|
|
|
|
}
|
|
|
|
|
2024-01-31 00:27:53 +01:00
|
|
|
if (ProcessingTracks.length > 0)
|
|
|
|
for (const Track of ProcessingTracks) {
|
|
|
|
if (!Track.HasAudio || !Track.HasMidi || !Track.HasCover)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
Track.Status = SongStatus.DEFAULT;
|
|
|
|
await Track.save();
|
|
|
|
}
|
|
|
|
|
2024-01-28 11:07:10 +01:00
|
|
|
res.json({
|
2024-01-31 00:27:53 +01:00
|
|
|
Bookmarks: req.user!.BookmarkedSongs.map(x => x.Package()),
|
|
|
|
Created: req.user!.CreatedTracks.map(x => x.Package(true)),
|
|
|
|
Library: req.user!.Library
|
2024-01-28 11:07:10 +01:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
App.post("/me/activate",
|
|
|
|
RequireAuthentication(),
|
|
|
|
ValidateBody(j.object({
|
|
|
|
SongID: j.string().uuid().required(),
|
|
|
|
ToOverride: j.string().pattern(/^sid_placeholder_(\d){1,3}$/i).required()
|
|
|
|
})),
|
|
|
|
async (req, res) => {
|
|
|
|
if (req.user!.Library!.length >= 15)
|
2024-01-31 00:27:53 +01:00
|
|
|
return res.status(400).send("You have too many active songs. Please deactivate some to free up space.");
|
2024-01-28 11:07:10 +01:00
|
|
|
|
|
|
|
if (req.user!.Library.findIndex(x => x.SongID.toLowerCase() === req.body.SongID.toLowerCase() || x.Overriding.toLowerCase() === req.body.ToOverride.toLowerCase()) !== -1)
|
2024-01-31 00:27:53 +01:00
|
|
|
return res.status(400).send("This song is already activated.");
|
2024-01-28 11:07:10 +01:00
|
|
|
|
2024-01-28 23:36:28 +01:00
|
|
|
const SongData = await Song.findOne({ where: { ID: req.body.SongID }, relations: { Author: true } });
|
|
|
|
if (!SongData)
|
2024-01-31 00:27:53 +01:00
|
|
|
return res.status(404).send("Provided song doesn't exist.");
|
2024-01-28 11:07:10 +01:00
|
|
|
|
2024-01-31 00:27:53 +01:00
|
|
|
if (SongData.IsDraft && (req.user!.PermissionLevel < UserPermissions.TrackVerifier && SongData.Author.ID !== req.user!.ID))
|
|
|
|
return res.status(403).send("You cannot activate this track, because it's a draft.");
|
2024-01-28 23:36:28 +01:00
|
|
|
|
2024-01-28 11:07:10 +01:00
|
|
|
req.user!.Library.push({ SongID: req.body.SongID.toLowerCase(), Overriding: req.body.ToOverride.toLowerCase() });
|
|
|
|
req.user!.save();
|
|
|
|
|
|
|
|
res.json(req.user!.Library);
|
|
|
|
})
|
|
|
|
|
|
|
|
App.post("/me/deactivate",
|
|
|
|
RequireAuthentication(),
|
|
|
|
ValidateBody(j.object({
|
|
|
|
SongID: j.string().uuid().required()
|
|
|
|
})),
|
|
|
|
async (req, res) => {
|
|
|
|
const idx = req.user!.Library.findIndex(x => x.SongID.toLowerCase() === req.body.SongID.toLowerCase());
|
|
|
|
if (idx === -1)
|
2024-01-31 00:27:53 +01:00
|
|
|
return res.status(400).send("This song is not activated.");
|
2024-01-28 11:07:10 +01:00
|
|
|
|
|
|
|
req.user?.Library.splice(idx, 1);
|
|
|
|
req.user?.save();
|
|
|
|
|
|
|
|
res.json(req.user?.Library);
|
|
|
|
})
|
|
|
|
|
|
|
|
App.post("/me/bookmark",
|
|
|
|
RequireAuthentication({ BookmarkedSongs: true }),
|
|
|
|
ValidateBody(j.object({
|
|
|
|
SongID: j.string().uuid().required()
|
|
|
|
})),
|
|
|
|
async (req, res) => {
|
|
|
|
if (req.user?.BookmarkedSongs.findIndex(x => x.ID.toLowerCase() === req.body.SongID.toLowerCase()) !== -1)
|
2024-01-31 00:27:53 +01:00
|
|
|
return res.status(400).send("You're already subscribed to this song.");
|
2024-01-28 11:07:10 +01:00
|
|
|
|
2024-01-28 22:02:29 +01:00
|
|
|
const SongData = await Song.findOne({ where: { ID: req.body.SongID }, relations: { Author: true } });
|
2024-01-28 11:07:10 +01:00
|
|
|
if (!SongData)
|
2024-01-31 00:27:53 +01:00
|
|
|
return res.status(404).send("Provided song doesn't exist.");
|
2024-01-28 11:07:10 +01:00
|
|
|
|
2024-01-31 00:27:53 +01:00
|
|
|
if (SongData.IsDraft && (req.user.PermissionLevel < UserPermissions.TrackVerifier && SongData.Author.ID !== req.user.ID))
|
|
|
|
return res.status(403).send("You cannot subscribe to this track, because it's a draft.");
|
2024-01-28 22:02:29 +01:00
|
|
|
|
2024-01-28 11:07:10 +01:00
|
|
|
req.user?.BookmarkedSongs.push(SongData);
|
|
|
|
req.user?.save();
|
|
|
|
|
|
|
|
res.json(req.user?.BookmarkedSongs.map(x => x.Package()));
|
|
|
|
})
|
|
|
|
|
|
|
|
App.post("/me/unbookmark",
|
|
|
|
RequireAuthentication(),
|
|
|
|
ValidateBody(j.object({
|
|
|
|
SongID: j.string().uuid().required()
|
|
|
|
})),
|
|
|
|
async (req, res) => {
|
|
|
|
const idx = req.user!.BookmarkedSongs.findIndex(x => x.ID.toLowerCase() === req.body.SongID.toLowerCase());
|
|
|
|
if (idx === -1)
|
2024-01-31 00:27:53 +01:00
|
|
|
return res.status(400).send("You aren't subscribed to this song.");
|
2024-01-28 11:07:10 +01:00
|
|
|
|
|
|
|
req.user?.BookmarkedSongs.splice(idx, 1);
|
|
|
|
req.user?.save();
|
|
|
|
|
|
|
|
res.json(req.user?.BookmarkedSongs.map(x => x.Package()));
|
|
|
|
})
|
|
|
|
|
2024-01-28 22:02:29 +01:00
|
|
|
App.get("/song/data/:InternalID",
|
|
|
|
RequireAuthentication(),
|
|
|
|
async (req, res) => {
|
2024-01-31 00:27:53 +01:00
|
|
|
const SongData = await Song.findOne({ where: { ID: req.params.InternalID }, relations: { Author: true } });
|
2024-01-28 11:07:10 +01:00
|
|
|
if (!SongData)
|
2024-01-31 00:27:53 +01:00
|
|
|
return res.status(404).send("Provided song doesn't exist.");
|
2024-01-28 22:02:29 +01:00
|
|
|
|
2024-01-31 00:27:53 +01:00
|
|
|
if (SongData.IsDraft && (req.user!.PermissionLevel < UserPermissions.TrackVerifier && SongData.Author.ID !== req.user!.ID))
|
2024-02-01 21:54:48 +01:00
|
|
|
return res.status(403).send("You cannot use assets of this track, because it's a draft.");
|
2024-01-28 11:07:10 +01:00
|
|
|
|
|
|
|
res.json(SongData.Package());
|
|
|
|
})
|
|
|
|
|
|
|
|
App.get("/available", (__, res) => res.json(Object.values(OriginalSparks!).filter(x => !!x.track).map(x => { return { Name: x.track.tt, Template: x.track.ti.substring(11) }; }).sort((a, b) => a.Name.toLowerCase() > b.Name.toLowerCase() ? 1 : -1)))
|
|
|
|
|
|
|
|
export default {
|
|
|
|
App,
|
|
|
|
DefaultAPI: "/api/library"
|
2024-01-22 00:41:59 +01:00
|
|
|
}
|