Added leaderboards

Thanks Heliato for help me ❤

Co-Authored-By: Heliato <[email protected]>
This commit is contained in:
Burlone
2025-03-30 01:15:45 +01:00
co-authored by Heliato
parent 6d27cade40
commit 883fc794a7
10 changed files with 367 additions and 62 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
BSD 3-Clause License
Copyright (c) 2024, Project Reload
Copyright (c) 2024-2025, Project Reload
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
+1 -1
View File
@@ -16,7 +16,7 @@
<button class="theme-toggle" id="themeToggle"></button>
<footer style="position: fixed; bottom: 0; width: 100%; text-align: center; color: gray; font-size: 14px; padding: 10px;">
Powered by Reload Backend - © 2024
Powered by Reload Backend - © 2024 - 2025
</footer>
<script>
+1 -1
View File
@@ -35,7 +35,7 @@
<button class="theme-toggle" id="themeToggle"></button>
<footer style="position: fixed; bottom: 0; width: 100%; text-align: center; color: gray; font-size: 14px; padding: 10px;">
Powered by Reload Backend - © 2024
Powered by Reload Backend - © 2024 - 2025
</footer>
<script>
+20
View File
@@ -0,0 +1,20 @@
const mongoose = require("mongoose");
const UserStatsSchema = new mongoose.Schema(
{
created: { type: Date, required: true },
accountId: { type: String, required: true, unique: true },
solo: { type: Object, required: true },
duo: { type: Object, required: true },
trio: { type: Object, required: true },
squad: { type: Object, required: true },
ltm: { type: Object, required: true },
},
{
collection: "userstats"
}
)
const model = mongoose.model("UserStatsSchema", UserStatsSchema);
module.exports = model;
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "reloadbackend",
"version": "1.1.7",
"version": "1.1.8",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "reloadbackend",
"version": "1.1.6",
"version": "1.1.8",
"license": "BSD-3-Clause license",
"dependencies": {
"axios": "^1.7.7",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "reloadbackend",
"version": "1.1.7",
"version": "1.1.8",
"description": "Created by Burlone, This is a modded backend, all main backend credits to lawin",
"main": "index.js",
"dependencies": {
+204
View File
@@ -0,0 +1,204 @@
const express = require("express");
const app = express.Router();
const User = require("../model/user.js");
const UserStats = require("../model/userstats.js");
const { verifyToken, verifyClient } = require("../tokenManager/tokenVerify.js");
const functions = require("../structs/functions.js");
const log = require("../structs/log.js");
app.get("/*/api/statsv2/leaderboards/:leaderboardName", async (req, res) => {
log.debug(`GET /*/api/statsv2/leaderboards/${req.params.leaderboardName} called`);
try {
const playlist = req.params.leaderboardName.split("playlist_default")[1];
const typeStat = req.params.leaderboardName.split("_keyboardmouse")[0].split("br_")[1];
const stats = await UserStats.find({});
if (!stats) return res.status(404).end();
const clientsStats = [];
const finalStats = [];
let maxSize = 100;
if (req.query.maxSize) {
if (req.query.maxSize <= 150 && req.query.maxSize > 0) {
maxSize = Number(req.query.maxSize);
} else {
return res.json({
error: "minSize: 1 / maxSize: 100"
});
}
}
for (var stat of stats) {
const findUser = await User.findOne({ accountId: stat.accountId });
if (!findUser) continue;
clientsStats.push({
displayName: findUser.username,
account: findUser.accountId,
value: stat[playlist][typeStat] || 0
});
}
clientsStats.sort((a, b) => b.value - a.value);
for (var finalStat of clientsStats) {
if (finalStats.length >= maxSize) continue;
finalStats.push({
displayName: finalStat.displayName,
account: finalStat.account,
value: finalStat.value
});
}
res.json({
maxSize: maxSize,
entries: finalStats
});
} catch (err) {
res.json({
error: "stat not found"
});
}
});
app.post("/fortnite/api/leaderboards/type/global/stat/:leaderboardName/window/:typeLeaderboard", async (req, res) => {
log.debug(`POST /fortnite/api/leaderboards/type/global/stat/${req.params.leaderboardName}/window/req.params.typeLeaderboard called`)
const playlist = functions.PlaylistNames(req.params.leaderboardName.split("m0_p")[1]).toLowerCase().replace("playlist_default", "");
const typeStat = req.params.leaderboardName.split("_pc")[0].split("br_")[1];
const stats = await UserStats.find({});
if (!stats) return res.status(404).end();
const entries = [];
for (var stat of stats) {
const user = await User.findOne({ accountId: stat.accountId });
if (!user) continue;
entries.push({
accountId: user.accountId,
displayName: user.username,
rank: 1,
value: stat[playlist][typeStat] || 0
});
}
entries.sort((a, b) => b.value - a.value);
entries.forEach((entry, index) => entry.rank = index + 1);
res.json({
statName: req.params.leaderboardName,
statWindow: req.params.typeLeaderboard,
entries: entries
});
});
app.post("/*/api/statsv2/query", verifyToken, async (req, res) => {
log.debug(`POST /*/api/statsv2/query called`);
if (!req.body.stats) return res.status(400).end();
const statKey = req.body.stats[0];
const playlist = statKey.split("playlist_default")[1];
const typeStat = statKey.split("_keyboardmouse")[0].split("br_")[1];
const stats = await UserStats.find({});
if (!stats) return res.status(404).end();
const clientsStats = [];
for (var owner of req.body.owners) {
const individualStat = await UserStats.findOne({ accountId: owner });
if (!individualStat) continue;
if (individualStat[playlist] == undefined) continue;
if (individualStat[playlist][typeStat] == undefined) continue;
clientsStats.push({
accountId: individualStat.accountId,
endTime: req.body.endTime || 0,
startTime: req.body.startTime || 0,
stats: {
[statKey]: individualStat[playlist][typeStat] || 0
}
});
}
res.json(clientsStats);
});
app.get("/fortnite/api/game/v2/leaderboards/cohort/:accountId", verifyToken, async (req, res) => {
log.debug(`GET /fortnite/api/game/v2/leaderboards/cohort/${req.params.accountId} called`);
res.json({});
});
app.get("/fortnite/api/stats/accountId/:accountId/bulk/window/:windowType", verifyToken, async (req, res) => {
const stats = await UserStats.findOne({ "accountId": req.params.accountId });
const allStats = ["solo", "duo", "squad"];
const statsList = [];
const allTypesStats = {
all: ["br_kills", "br_score", "br_matchesplayed", "br_minutesplayed"],
solo: ["br_placetop1", "br_placetop10", "br_placetop25"],
duo: ["br_placetop1", "br_placetop5", "br_placetop12"],
squad: ["br_placetop1", "br_placetop3", "br_placetop6"]
}
for (var stat of allStats) {
for (var typeStat of allTypesStats.all) {
statsList.push({
name: `${typeStat}_pc_m0_p${functions.PlaylistNames(stat)}`,
value: stats[stat][typeStat.replace("br_", "")] || 0,
window: req.params.windowType,
ownerType: 1
});
}
for (var typeStats of allTypesStats[stat]) {
statsList.push({
name: `${typeStats}_pc_m0_p${functions.PlaylistNames(stat)}`,
value: stats[stat][typeStats.replace("br_", "")] || 0,
window: req.params.windowType,
ownerType: 1
});
}
}
res.json(statsList);
});
app.get("/*/api/statsv2/account/:accountId", verifyToken, async (req, res) => {
const stats = await UserStats.findOne({ accountId: req.params.accountId });
res.json({
accountId: req.params.accountId,
endTime: 0,
startTime: req.query.startTime || 0,
stats: {
br_placetop1_keyboardmouse_m0_playlist_defaultsolo: stats.solo.placetop1 || 0,
br_placetop1_keyboardmouse_m0_playlist_defaultduo: stats.duo.placetop1 || 0,
br_placetop1_keyboardmouse_m0_playlist_defaultsquad: stats.squad.placetop1 || 0,
br_placetop1_keyboardmouse_m0_playlist_solidgold_solo: stats.ltm.wins || 0,
br_placetop10_keyboardmouse_m0_playlist_defaultsolo: stats.solo.placetop10 || 0,
br_placetop5_keyboardmouse_m0_playlist_defaultduo: stats.duo.placetop5 || 0,
br_placetop3_keyboardmouse_m0_playlist_defaultsquad: stats.squad.placetop3 || 0,
br_placetop25_keyboardmouse_m0_playlist_defaultsolo: stats.solo.placetop25 || 0,
br_placetop12_keyboardmouse_m0_playlist_defaultduo: stats.duo.placetop12 || 0,
br_placetop6_keyboardmouse_m0_playlist_defaultsquad: stats.squad.placetop6 || 0,
br_kills_keyboardmouse_m0_playlist_defaultsolo: stats.solo.kills || 0,
br_kills_keyboardmouse_m0_playlist_defaultduo: stats.duo.kills || 0,
br_kills_keyboardmouse_m0_playlist_defaultsquad: stats.squad.kills || 0,
br_kills_keyboardmouse_m0_playlist_solidgold_solo: stats.ltm.kills || 0,
br_matchesplayed_keyboardmouse_m0_playlist_defaultsolo: stats.solo.matchesplayed || 0,
br_matchesplayed_keyboardmouse_m0_playlist_defaultduo: stats.duo.matchesplayed || 0,
br_matchesplayed_keyboardmouse_m0_playlist_defaultsquad: stats.squad.matchesplayed || 0,
br_matchesplayed_keyboardmouse_m0_playlist_solidgold_solo: stats.ltm.matchesplayed || 0,
br_minutesplayed_keyboardmouse_m0_playlist_defaultsolo: stats.solo.minutesplayed || 0,
br_minutesplayed_keyboardmouse_m0_playlist_defaultduo: stats.duo.minutesplayed || 0,
br_minutesplayed_keyboardmouse_m0_playlist_defaultsquad: stats.squad.minutesplayed || 0,
br_minutesplayed_keyboardmouse_m0_playlist_solidgold_solo: stats.ltm.minutesplayed || 0,
br_playersoutlived_keyboardmouse_m0_playlist_defaultsolo: stats.solo.playersoutlived || 0,
br_playersoutlived_keyboardmouse_m0_playlist_defaultduo: stats.duo.playersoutlived || 0,
br_playersoutlived_keyboardmouse_m0_playlist_defaultsquad: stats.squad.playersoutlived || 0,
br_playersoutlived_keyboardmouse_m0_playlist_solidgold_solo: stats.ltm.playersoutlived || 0,
br_score_keyboardmouse_m0_playlist_defaultsolo: stats.solo.score || 0,
br_score_keyboardmouse_m0_playlist_defaultduo: stats.duo.score || 0,
br_score_keyboardmouse_m0_playlist_defaultsquad: stats.squad.score || 0,
br_score_keyboardmouse_m0_playlist_solidgold_solo: stats.ltm.score || 0
}
});
});
module.exports = app;
+1 -56
View File
@@ -27,62 +27,7 @@ app.get("/fortnite/api/game/v2/matchmakingservice/ticket/player/*", verifyToken,
return res.status(400).end();
}
const rawPlaylist = bucketId.split(":")[3];
let playlist = rawPlaylist.toLowerCase();
if (playlist === "2") {
playlist = "playlist_defaultsolo";
} else if (playlist === "10") {
playlist = "playlist_defaultduo";
} else if (playlist === "9") {
playlist = "playlist_defaultsquad";
} else if (playlist === "50") {
playlist = "playlist_50v50";
} else if (playlist === "11") {
playlist = "playlist_50v50";
} else if (playlist === "13") {
playlist = "playlist_highexplosives_squads";
} else if (playlist === "22") {
playlist = "playlist_5x20";
} else if (playlist === "36") {
playlist = "playlist_blitz_solo";
} else if (playlist === "37") {
playlist = "playlist_blitz_duos";
} else if (playlist === "19") {
playlist = "playlist_blitz_squad";
} else if (playlist === "33") {
playlist = "playlist_carmine";
} else if (playlist === "32") {
playlist = "playlist_fortnite";
} else if (playlist === "23") {
playlist = "playlist_highexplosives_solo";
} else if (playlist === "24") {
playlist = "playlist_highexplosives_squads";
} else if (playlist === "44") {
playlist = "playlist_impact_solo";
} else if (playlist === "45") {
playlist = "playlist_impact_duos";
} else if (playlist === "46") {
playlist = "playlist_impact_squads";
} else if (playlist === "35") {
playlist = "playlist_playground";
} else if (playlist === "30") {
playlist = "playlist_skysupply";
} else if (playlist === "42") {
playlist = "playlist_skysupply_duos";
} else if (playlist === "43") {
playlist = "playlist_skysupply_squads";
} else if (playlist === "41") {
playlist = "playlist_snipers";
} else if (playlist === "39") {
playlist = "playlist_snipers_solo";
} else if (playlist === "40") {
playlist = "playlist_snipers_duos";
} else if (playlist === "26") {
playlist = "playlist_solidgold_solo";
} else if (playlist === "27") {
playlist = "playlist_solidgold_squads";
} else if (playlist === "28") {
playlist = "playlist_showdownalt_solo";
}
let playlist = functions.PlaylistNames(rawPlaylist).toLowerCase();
const gameServers = config.gameServerIP;
let selectedServer = gameServers.find(server => server.split(":")[2].toLowerCase() === playlist);
+69
View File
@@ -371,6 +371,7 @@ async function registerUser(discordId, username, email, plainPassword) {
}).then(async (i) => {
await Profile.create({ created: i.created, accountId: i.accountId, profiles: profileManager.createProfiles(i.accountId) });
await Friends.create({ created: i.created, accountId: i.accountId });
profileManager.createUserStatsProfiles(i.accountId);
});
} catch (err) {
if (err.code == 11000) {
@@ -409,6 +410,73 @@ async function createSAC(code, username, creator) {
return { message: "You successfully created an **Support a Creator** Code!", status: 200}
}
function PlaylistNames(playlist) {
switch (playlist) {
case "2":
return "Playlist_DefaultSolo";
case "10":
return "Playlist_DefaultDuo";
case "9":
return "Playlist_DefaultSquad";
case "50":
return "Playlist_50v50";
case "11":
return "Playlist_50v50";
case "13":
return "Playlist_HighExplosives_Squads";
case "22":
return "Playlist_5x20";
case "36":
return "Playlist_Blitz_Solo";
case "37":
return "Playlist_Blitz_Duos";
case "19":
return "Playlist_Blitz_Squad";
case "33":
return "Playlist_Carmine";
case "32":
return "Playlist_Fortnite";
case "23":
return "Playlist_HighExplosives_Solo";
case "24":
return "Playlist_HighExplosives_Squads";
case "44":
return "Playlist_Impact_Solo";
case "45":
return "Playlist_Impact_Duos";
case "46":
return "Playlist_Impact_Squads";
case "35":
return "Playlist_Playground";
case "30":
return "Playlist_SkySupply";
case "42":
return "Playlist_SkySupply_Duos";
case "43":
return "Playlist_SkySupply_Squads";
case "41":
return "Playlist_Snipers";
case "39":
return "Playlist_Snipers_Solo";
case "40":
return "Playlist_Snipers_Duos";
case "26":
return "Playlist_SolidGold_Solo";
case "27":
return "Playlist_SolidGold_Squads";
case "28":
return "Playlist_ShowdownAlt_Solo";
case "solo":
return "2";
case "duo":
return "10";
case "squad":
return "9";
default:
return playlist;
}
}
function DecodeBase64(str) {
return Buffer.from(str, 'base64').toString();
}
@@ -433,6 +501,7 @@ module.exports = {
getPresenceFromUser,
registerUser,
createSAC,
PlaylistNames,
DecodeBase64,
UpdateTokens
}
+67
View File
@@ -1,4 +1,5 @@
const fs = require("fs");
const UserStats = require("../model/userstats.js");
function createProfiles(accountId) {
let profiles = {};
@@ -16,6 +17,71 @@ function createProfiles(accountId) {
return profiles;
}
async function createUserStatsProfiles(accountId) {
await UserStats.create({
created: new Date().toISOString(),
accountId: accountId,
solo: {
placetop1: 0,
placetop10: 0,
placetop25: 0,
score: 0,
kills: 0,
deaths: 0,
kd: 0,
matchesplayed: 0,
minutesplayed: 0,
playersoutlived: 0
},
duo: {
placetop1: 0,
placetop5: 0,
placetop12: 0,
score: 0,
kills: 0,
deaths: 0,
kd: 0,
matchesplayed: 0,
minutesplayed: 0,
playersoutlived: 0
},
trio: {
placetop1: 0,
placetop3: 0,
placetop6: 0,
score: 0,
kills: 0,
deaths: 0,
kd: 0,
matchesplayed: 0,
minutesplayed: 0,
playersoutlived: 0
},
squad: {
placetop1: 0,
placetop3: 0,
placetop6: 0,
score: 0,
kills: 0,
deaths: 0,
kd: 0,
matchesplayed: 0,
minutesplayed: 0,
playersoutlived: 0
},
ltm: {
wins: 0,
score: 0,
kills: 0,
deaths: 0,
kd: 0,
matchesplayed: 0,
minutesplayed: 0,
playersoutlived: 0
},
});
}
async function validateProfile(profileId, profiles) {
try {
let profile = profiles.profiles[profileId];
@@ -30,5 +96,6 @@ async function validateProfile(profileId, profiles) {
module.exports = {
createProfiles,
createUserStatsProfiles,
validateProfile
}