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;