From 8366f3df1813f3cb45205b46b851f5fa40eee7e5 Mon Sep 17 00:00:00 2001 From: DanIIII64 Date: Mon, 26 Jan 2026 20:26:41 +0100 Subject: [PATCH] just some shit just some missing endpoint fix, no point in it just if you want to make the parental control shit to work and fn crew eula and something on the 28.xx version, 27.xx, and 23.xx --- routes/avatar.js | 17 ++++ routes/contentControls.js | 22 ++++++ routes/contentRules.js | 26 +++++++ routes/favouriteCreativeMaps.js | 17 ++++ routes/fixUsersApi.js | 48 ++++++++++++ routes/fixes.js | 133 ++++++++++++++++++++++++++++++++ routes/fnCrewEULA.js | 20 +++++ routes/friendsRecent.js | 16 ++++ routes/legacyUnlock.js | 22 ++++++ routes/missingfixes.js | 61 +++++++++++++++ routes/motd.js | 13 ++++ routes/parentalControlPin.js | 23 ++++++ routes/publickey.js | 15 ++++ routes/unlockLinks.js | 25 ++++++ 14 files changed, 458 insertions(+) create mode 100644 routes/avatar.js create mode 100644 routes/contentControls.js create mode 100644 routes/contentRules.js create mode 100644 routes/favouriteCreativeMaps.js create mode 100644 routes/fixUsersApi.js create mode 100644 routes/fixes.js create mode 100644 routes/fnCrewEULA.js create mode 100644 routes/friendsRecent.js create mode 100644 routes/legacyUnlock.js create mode 100644 routes/missingfixes.js create mode 100644 routes/motd.js create mode 100644 routes/parentalControlPin.js create mode 100644 routes/publickey.js create mode 100644 routes/unlockLinks.js diff --git a/routes/avatar.js b/routes/avatar.js new file mode 100644 index 0000000..a6ff43b --- /dev/null +++ b/routes/avatar.js @@ -0,0 +1,17 @@ +// routes/avatar.js +const express = require("express"); +const router = express.Router(); + +// GET /v1/avatar/fortnite/ids +router.get("/v1/avatar/fortnite/ids", (req, res) => { + const ids = req.query.accountIds?.split(",") || []; + + const avatars = ids.map(id => ({ + accountId: id, + avatarUrl: "https://fortnite-public-service-prod11.ol.epicgames.com/fortnite/api/game/v2/profile/avatar/default" + })); + + res.json(avatars); +}); + +module.exports = router; diff --git a/routes/contentControls.js b/routes/contentControls.js new file mode 100644 index 0000000..d43225b --- /dev/null +++ b/routes/contentControls.js @@ -0,0 +1,22 @@ +const express = require("express"); +const router = express.Router(); + +// GET /content-controls/:accountId/rules/namespaces/fn +router.get("/content-controls/:accountId/rules/namespaces/fn", (req, res) => { + const { accountId } = req.params; + + console.log(`[CONTENT-CONTROLS] Rules requested for ${accountId}`); + + return res.json({ + accountId: accountId, + namespaces: { + fn: { + restrictions: [], + version: 1 + } + }, + updatedAt: new Date().toISOString() + }); +}); + +module.exports = router; diff --git a/routes/contentRules.js b/routes/contentRules.js new file mode 100644 index 0000000..4e0f678 --- /dev/null +++ b/routes/contentRules.js @@ -0,0 +1,26 @@ +const express = require("express"); +const router = express.Router(); + +// POST /content-controls/{accountId}/rules/namespaces/fn +router.post("/content-controls/:accountId/rules/namespaces/fn", (req, res) => { + console.log(`[CONTENT RULES] Request for ${req.params.accountId}`); + + res.json({ + namespace: "fn", + rules: { + "ageRating": { + enabled: false, + value: "UNRESTRICTED" + }, + "chat": { + enabled: true + }, + "ugc": { + enabled: true + } + }, + updatedAt: new Date().toISOString() + }); +}); + +module.exports = router; diff --git a/routes/favouriteCreativeMaps.js b/routes/favouriteCreativeMaps.js new file mode 100644 index 0000000..5d3ce66 --- /dev/null +++ b/routes/favouriteCreativeMaps.js @@ -0,0 +1,17 @@ +const express = require("express"); +const router = express.Router(); + +// GET /fortnite/api/game/v2/creative/favorites/:accountId +router.get("/fortnite/api/game/v2/creative/favorites/:accountId", (req, res) => { + const { accountId } = req.params; + const { limit } = req.query; + + console.log(`[CREATIVE] Favorites request for ${accountId}, limit=${limit}`); + + // Fortnite empty listet is elfogad + return res.json({ + favorites: [] + }); +}); + +module.exports = router; diff --git a/routes/fixUsersApi.js b/routes/fixUsersApi.js new file mode 100644 index 0000000..aecac18 --- /dev/null +++ b/routes/fixUsersApi.js @@ -0,0 +1,48 @@ +const express = require("express"); +const router = express.Router(); + +/* +|-------------------------------------------------------------------------- +| LINKS HISTORY +|-------------------------------------------------------------------------- +| GET /api/v1/links/history/:accountId?limit=30 +*/ +router.get("/api/v1/links/history/:accountId", (req, res) => { + res.json({ + links: [], + accountId: req.params.accountId, + limit: Number(req.query.limit) || 30 + }); +}); + +/* +|-------------------------------------------------------------------------- +| LFG SETTINGS +|-------------------------------------------------------------------------- +| PATCH /api/v1/lfg/Fortnite/users/:accountId/settings +*/ +router.patch("/api/v1/lfg/Fortnite/users/:accountId/settings", (req, res) => { + res.json({ + accountId: req.params.accountId, + settings: req.body || {}, + updated: true + }); +}); + +/* +|-------------------------------------------------------------------------- +| BR INVENTORY (VERY IMPORTANT STUB) +|-------------------------------------------------------------------------- +| GET /fortnite/api/game/v2/br-inventory/account/:accountId +*/ +router.get("/fortnite/api/game/v2/br-inventory/account/:accountId", (req, res) => { + res.json({ + accountId: req.params.accountId, + inventory: { + currency: [], + items: [] + } + }); +}); + +module.exports = router; diff --git a/routes/fixes.js b/routes/fixes.js new file mode 100644 index 0000000..fe9baa8 --- /dev/null +++ b/routes/fixes.js @@ -0,0 +1,133 @@ +const express = require("express"); +const app = express.Router(); + +/** + * Helper: empty OK responses + */ +const ok = (req, res) => res.status(200).json({}); +const noContent = (req, res) => res.sendStatus(204); +const accepted = (req, res) => res.sendStatus(202); + +/* ========================= + DATAROUTER / TELEMETRY +========================= */ + +// basic datarouter +app.post("/datarouter/api/v1/public/data", accepted); + +// FN client event stream +app.post("/datarouter/api/v1/public/data/clients", accepted); + +// EOS / SDK telemetry (note the /telemetry/data prefix) +app.post("/telemetry/data/datarouter/api/v1/public/data", accepted); + +/* ========================= + HOTCONFIG / CONTENT +========================= */ + +app.get("/hotconfigs/v2/livefn.json", (req, res) => { + res.json({ + version: 1, + configs: {} + }); +}); + +app.get("/api/content/v2/launch-data", ok); + +/* ========================= + PROFILE / USER PREFS +========================= */ + +app.put("/profile/play_region", noContent); +app.put("/profile/languages", noContent); +app.put("/profile/privacy_settings", noContent); + +/* ========================= + SOCIAL / FRIENDS +========================= */ + +app.get("/epic/friends/v1/:accountId/blocklist", (req, res) => { + res.json({ blocked: [] }); +}); + +app.get("/content-controls/:accountId", ok); + +app.get("/party/api/v1/Fortnite/user/:accountId/settings/privacy", ok); + +/* ========================= + INTERACTIONS (SOCIAL FEED) +========================= */ + +app.get("/api/v2/interactions/latest/Fortnite/:accountId", (req, res) => { + res.json({ entries: [] }); +}); + +app.get("/api/v2/interactions/aggregated/Fortnite/:accountId", (req, res) => { + res.json({ stats: {} }); +}); + +/* ========================= + LFG +========================= */ + +app.get("/api/v1/lfg/Fortnite/users/:accountId/settings", ok); + +/* ========================= + ACCOUNTS (PUBLIC LOOKUPS) +========================= */ + +app.get("/api/v1/public/accounts", (req, res) => { + const ids = [].concat(req.query.accountId || []); + res.json( + ids.map(id => ({ + id, + displayName: "Player", + externalAuths: {} + })) + ); +}); + +/* ========================= + OAUTH MISC +========================= */ + +app.post("/epic/oauth/v2/tokenInfo", ok); + +/* ========================= + FEEDBACK / LOG UPLOADS +========================= */ + +app.get("/api/v1/access/fortnite/client-feedback/*", noContent); +app.post("/fortnite/api/feedback/*", noContent); + +/* ========================= + LINKS / LOCK STATUS +========================= */ + +app.post("/api/v1/links/lock-status/:accountId/check", (req, res) => { + res.json({ locked: false }); +}); + +/* ========================= + MOTD SURFACES +========================= */ + +app.post("/api/v1/fortnite-br/surfaces/:surface/target", (req, res) => { + res.json({ + entries: [] + }); +}); + +/* ========================= + APP / REGION +========================= */ + +app.get("/app_installation/status", ok); + +app.get("/region", (req, res) => { + res.json({ + region: "EU" + }); +}); + +module.exports = app; diff --git a/routes/fnCrewEULA.js b/routes/fnCrewEULA.js new file mode 100644 index 0000000..251ecf4 --- /dev/null +++ b/routes/fnCrewEULA.js @@ -0,0 +1,20 @@ +const express = require("express"); +const router = express.Router(); + +// GET /eulatracking/api/shared/agreements/fn-crew-terms +router.get("/eulatracking/api/shared/agreements/fn-crew-terms", (req, res) => { + console.log("[EULA] Crew terms requested"); + + const locale = req.query.locale || "en"; + + return res.json({ + key: "fn-crew-terms", + version: 1, + locale: locale, + content: "By using this Fortnite private backend, you agree to nothing. This is a fake EULA for private server use.", + accepted: true, + acceptedDate: new Date().toISOString() + }); +}); + +module.exports = router; diff --git a/routes/friendsRecent.js b/routes/friendsRecent.js new file mode 100644 index 0000000..34c7453 --- /dev/null +++ b/routes/friendsRecent.js @@ -0,0 +1,16 @@ +// routes/friendsRecent.js +const express = require("express"); +const router = express.Router(); + +// GET /friends/api/v1/:accountId/recent/fortnite +router.get("/friends/api/v1/:accountId/recent/fortnite", (req, res) => { + const accountId = req.params.accountId; + + // Dummy recent players lista (üresen is működik) + res.json({ + accountId: accountId, + recentPlayers: [] + }); +}); + +module.exports = router; diff --git a/routes/legacyUnlock.js b/routes/legacyUnlock.js new file mode 100644 index 0000000..47cd5b5 --- /dev/null +++ b/routes/legacyUnlock.js @@ -0,0 +1,22 @@ +const express = require("express"); +const router = express.Router(); + +// ================================ +// LEGACY UNLOCK STUB +// ================================ +router.delete("/api/v1/links/legacy-unlock/:accountId", (req, res) => { + const { accountId } = req.params; + + // Csak logoljuk, de nem végzünk tényleges unlockot + console.log(`[LegacyUnlock] DELETE called for account: ${accountId}`); + + // Visszaadjuk, hogy sikeres volt + res.json({ + accountId: accountId, + unlocked: true, // mindig sikeres + serverTime: new Date().toISOString(), + responseVersion: 1 + }); +}); + +module.exports = router; diff --git a/routes/missingfixes.js b/routes/missingfixes.js new file mode 100644 index 0000000..2904d2d --- /dev/null +++ b/routes/missingfixes.js @@ -0,0 +1,61 @@ +const express = require("express"); +const router = express.Router(); + +/* helpers */ +const ok = (req, res) => res.status(200).json({}); +const noContent = (req, res) => res.sendStatus(204); + +/* ========================= + CLIENT FEEDBACK / LOG UPLOAD + (urlencoded path miatt wildcard!) +========================= */ + +router.get( + "/api/v1/access/fortnite/client-feedback*", + noContent +); + +/* ========================= + PROFILES (PUT /profiles) +========================= */ + +router.put("/profiles", noContent); + +/* ========================= + FORTNITE TRACKS +========================= */ + +router.get( + "/api/v1/games/fortnite/tracks/query", + (req, res) => { + res.json({ + tracks: [] + }); + } +); + +/* ========================= + TAGS +========================= */ + +router.get("/api/v1/public/tags", (req, res) => { + res.json({ + tags: [] + }); +}); + +/* ========================= + BLURL FILES (dynamic hash path) +========================= */ + +router.get("/:hash/master.blurl", noContent); +router.get("/:hash/main.blurl", noContent); + +/* ========================= + SAFETY NET (optional) + only for weird FN GETs +========================= */ + +// router.get("*", noContent); + +module.exports = router; diff --git a/routes/motd.js b/routes/motd.js new file mode 100644 index 0000000..b7e8ea7 --- /dev/null +++ b/routes/motd.js @@ -0,0 +1,13 @@ +// routes/motd.js +const express = require("express"); +const router = express.Router(); + +// POST /api/v1/fortnite-br/surfaces/motd/interactions +router.post("/api/v1/fortnite-br/surfaces/motd/interactions", (req, res) => { + console.log("[MOTD] Interaction received:", req.body); + + // Epic általában üres 204-et vár + res.status(204).send(); +}); + +module.exports = router; diff --git a/routes/parentalControlPin.js b/routes/parentalControlPin.js new file mode 100644 index 0000000..15f6d1e --- /dev/null +++ b/routes/parentalControlPin.js @@ -0,0 +1,23 @@ +const express = require("express"); +const router = express.Router(); + +// ================================ +// VERIFY PIN STUB +// ================================ +router.post("/content-controls/:accountId/verify-pin", (req, res) => { + const { accountId } = req.params; + const { pin } = req.body; + + // Csak logoljuk, de nem csinálunk valódi ellenőrzést + console.log(`[ContentControls] Verify PIN called for account: ${accountId}, pin: ${pin}`); + + // Visszaadjuk, hogy sikeres volt + res.json({ + accountId: accountId, + pinVerified: true, // mindig sikeres + serverTime: new Date().toISOString(), + responseVersion: 1 + }); +}); + +module.exports = router; diff --git a/routes/publickey.js b/routes/publickey.js new file mode 100644 index 0000000..8a84502 --- /dev/null +++ b/routes/publickey.js @@ -0,0 +1,15 @@ +const express = require("express"); +const router = express.Router(); + +// POST /publickey/v1/publickey/ +router.post("/publickey/v1/publickey/", (req, res) => { + console.log("[PUBLICKEY] Client requested public key"); + + return res.json({ + "key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArandomfakekeyfortnitebackend1234567890ABCD\n-----END PUBLIC KEY-----", + "algorithm": "RS256", + "expires_at": "2099-01-01T00:00:00Z" + }); +}); + +module.exports = router; diff --git a/routes/unlockLinks.js b/routes/unlockLinks.js new file mode 100644 index 0000000..06b98ab --- /dev/null +++ b/routes/unlockLinks.js @@ -0,0 +1,25 @@ +const express = require("express"); +const router = express.Router(); + +// ================================ +// UNLOCK LINKS STUB +// ================================ +router.get("/api/v1/links/unlock/:accountId", (req, res) => { + const { accountId } = req.params; + const { limit, ratingAuthority, rating } = req.query; + + console.log(`[UnlockLinks] GET called for account: ${accountId}, limit: ${limit}, ratingAuthority: ${ratingAuthority}, rating: ${rating}`); + + // Visszaadunk egy üres listát, vagy igény szerint mockolt unlock adatot + res.json({ + accountId: accountId, + unlockedLinks: [], // üres tömb, vagy ide tehetsz mock adatot + limit: parseInt(limit) || 0, + ratingAuthority: ratingAuthority || null, + rating: rating || null, + serverTime: new Date().toISOString(), + responseVersion: 1 + }); +}); + +module.exports = router;