mirror of
https://github.com/ApfelTeeSaft/Reload-Backend.git
synced 2026-08-26 19:33:26 +00:00
Added leaderboards
Thanks Heliato for help me ❤ Co-Authored-By: Heliato <[email protected]>
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
Generated
+2
-2
@@ -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
@@ -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": {
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user