156 lines
7.2 KiB
TypeScript
156 lines
7.2 KiB
TypeScript
import { Err } from "./Logger";
|
|
import { red } from "colorette";
|
|
import { FULL_SERVER_ROOT } from "./Constants";
|
|
import { User } from "../Schemas/User";
|
|
import { Song } from "../Schemas/Song";
|
|
|
|
export let FullFortnitePages: { [key: string]: any } | null = null;
|
|
export let OriginalSparks: {[key: string]: any} | null = null;
|
|
let LastContentDownloadDate: Date = new Date(0); // set it to 1970 as default cuz im not boutta check if its null
|
|
|
|
GenerateFortnitePages(null);
|
|
|
|
export async function GenerateFortnitePages(ForUser: User | null): Promise<{ Success: boolean, FNPages: { [key: string]: unknown } | null }> {
|
|
let status;
|
|
let data;
|
|
if (FullFortnitePages === null || Date.now() > LastContentDownloadDate.getTime() + 30 * 60 * 1000) {
|
|
const response = await fetch("https://fortnitecontent-website-prod07.ol.epicgames.com/content/api/pages/fortnite-game");
|
|
status = response.status;
|
|
data = await response.json();
|
|
} else {
|
|
status = 200;
|
|
data = FullFortnitePages;
|
|
}
|
|
/*const { status, data } = // check if 30 minutes have passed since last content update. if so, get a new copy of pages, if not, fuck off
|
|
FullFortnitePages === null || Date.now() > LastContentDownloadDate.getTime() + 30 * 60 * 1000 ?
|
|
await fetch("https://fortnitecontent-website-prod07.ol.epicgames.com/content/api/pages/fortnite-game") :
|
|
FullFortnitePages;*/
|
|
|
|
let OGSparks;
|
|
|
|
if (OriginalSparks === null || Date.now() > LastContentDownloadDate.getTime() + 30 * 60 * 1000) {
|
|
const response = await fetch("https://fortnitecontent-website-prod07.ol.epicgames.com/content/api/pages/fortnite-game/spark-tracks");
|
|
OGSparks = {status: 200, data: await response.json()}
|
|
} else {
|
|
OGSparks = OriginalSparks
|
|
}
|
|
|
|
|
|
|
|
FullFortnitePages = {
|
|
...data,
|
|
sparkTracks: {
|
|
...data.sparkTracks,
|
|
lastModified: new Date().toISOString()
|
|
}
|
|
};
|
|
OriginalSparks = OGSparks.data;
|
|
LastContentDownloadDate = new Date();
|
|
|
|
if (!ForUser)
|
|
return { Success: true, FNPages: null };
|
|
|
|
if (status !== 200 || OGSparks.status !== 200) {
|
|
Err(`Failed to get Fortnite pages: ${red(status)}, ${red(OGSparks.status)}`);
|
|
console.log(data);
|
|
process.exit(-1); // very big fuck moment, we literally cannot run the server without fortnitepages
|
|
}
|
|
|
|
const AllSongs: { [key: string]: unknown } = {}; // too lazy to actually write a schema for this :D
|
|
const Overrides = ForUser.Library.map(x => { return { ...x, SongData: Song.findOne({ where: { ID: x.SongID } }) }; });
|
|
const UsersLibrary = await Promise.all(Overrides.map(x => x.SongData));
|
|
|
|
for (const Song of UsersLibrary)
|
|
{
|
|
if (!Song)
|
|
continue;
|
|
|
|
const OverridingAs = Overrides.find(x => x.SongID === Song.ID);
|
|
if (!OverridingAs)
|
|
continue;
|
|
|
|
const OriginalTrack = Object.values(OriginalSparks!).find(x => x.track?.ti === `SparksSong:${OverridingAs.Overriding.toLowerCase()}`);
|
|
if (!OriginalTrack)
|
|
continue;
|
|
|
|
AllSongs[OriginalTrack._title] = {
|
|
_title: OriginalTrack._title,
|
|
_noIndex: false,
|
|
_activeDate: "2023-01-01T01:00:00.000Z",
|
|
_locale: "en-US",
|
|
_templateName: "track",
|
|
lastModified: new Date().toISOString(),
|
|
track: {
|
|
tt: Song.Name, // tt - Title,
|
|
an: Song.ArtistName, // an - Artist Name
|
|
mm: Song.Scale, // mm - Minor, Major
|
|
mk: Song.Key, // mk - Music Key
|
|
ab: Song.Album, // ab - Album
|
|
su: OriginalTrack._title, // su - Song UUID
|
|
ry: Song.Year, // ry - Release Year
|
|
mt: Song.Tempo, // mt - Music Timing (?)
|
|
au: Song.Cover ?? `${FULL_SERVER_ROOT}/song/download/${Song.ID}/cover.png`, // au - Album Cover
|
|
gt: [ "Jam-LoopIsUnpitched-Beat" ], // gt - Gameplay Tags (but in a different format: Example.Gameplay.Tag -> Example-Gameplay-Tag)
|
|
ti: `SparksSong:${OverridingAs.Overriding.toLowerCase()}`,
|
|
mu: Song.Midi ?? `${FULL_SERVER_ROOT}/song/download/${Song.ID}/midi.mid`, // mu - Song Midi (encrypted)
|
|
dn: Song.Length, // dn - Track Length (in seconds)
|
|
ge: [ "Pop" ], // ge - Genres
|
|
in: {
|
|
ba: Song.BassDifficulty,
|
|
pb: Song.BassDifficulty,
|
|
pd: Song.DrumsDifficulty,
|
|
ds: Song.DrumsDifficulty,
|
|
pg: Song.GuitarDifficulty,
|
|
gr: Song.GuitarDifficulty,
|
|
vl: Song.VocalsDifficulty,
|
|
_type: "SparkTrackIntensities"
|
|
}, // in - Intensities (those white bars you see)
|
|
sib: "Bass", // sib - Bass ID to use (only Bass possible)
|
|
sid: "Drum", // sid - Drums ID to use (only Drum possible)
|
|
sig: Song.GuitarStarterType, // sig - Guitar ID to use (Keytar/Guitar)
|
|
siv: "Vocals", // siv - Vocals ID to use (only Vocals possible)
|
|
qi: JSON.stringify({ // qi - Query Information (frontend related display stuff and language vocals channel related stuff)
|
|
sid: Song.ID, // sid - Song UUID
|
|
pid: Song.PID, // pid - Playlist Asset ID
|
|
title: OriginalTrack._title, // title - Song Name - same as _title
|
|
tracks: [
|
|
{
|
|
part: "ds", // Drum Set
|
|
channels: [ "FL", "FR" ],
|
|
vols: [ 4, 4 ]
|
|
},
|
|
{
|
|
part: "bs", // Bass Set (not bullshit)
|
|
channels: [ "FL", "FR" ],
|
|
vols: [ 4, 4 ]
|
|
},
|
|
{
|
|
part: "gs", // Guitar Set
|
|
channels: [ "FL", "FR" ],
|
|
vols: [ 4, 4 ]
|
|
},
|
|
{
|
|
part: "vs", // Vocal Set (not Visual Studio)
|
|
channels: [ "FL", "FR" ],
|
|
vols: [ 4, 4 ]
|
|
},
|
|
{
|
|
part: "fs", // Fart Set (jk i have no idea)
|
|
channels: [ "FL", "FR" ],
|
|
vols: [ 4, 4 ]
|
|
}
|
|
],
|
|
preview: {
|
|
starttime: 0
|
|
}
|
|
}),
|
|
ld: Song.Lipsync ?? OriginalTrack.track.ld, // ld - Lipsync Data (it's literally a uasset)
|
|
jc: OriginalTrack.track.jc, // jc - Join Code (UEFN empty island with nothing - possibly downloads assets)
|
|
sn: OriginalTrack._title, // sn - Song Name - same as _title
|
|
_type: "SparkTrack"
|
|
}
|
|
};
|
|
}
|
|
|
|
return { Success: true, FNPages: AllSongs };
|
|
} |