diff options
author | TheArcaneBrony <myrainbowdash949@gmail.com> | 2022-08-26 04:14:54 +0200 |
---|---|---|
committer | TheArcaneBrony <myrainbowdash949@gmail.com> | 2022-09-04 10:48:14 +0200 |
commit | 8ba8828fae6a80c3b30b6bea513be4a9620c8705 (patch) | |
tree | e627fb33f4059ab55109d7efbead25d1570c8ee7 /src/api | |
parent | Prettier (diff) | |
download | server-8ba8828fae6a80c3b30b6bea513be4a9620c8705.tar.xz |
Basic client patching system
Diffstat (limited to 'src/api')
-rw-r--r-- | src/api/Server.ts | 3 | ||||
-rw-r--r-- | src/api/middlewares/TestClient.ts | 15 | ||||
-rw-r--r-- | src/api/util/TestClientPatcher.ts | 107 | ||||
-rw-r--r-- | src/api/util/index.ts | 2 |
4 files changed, 123 insertions, 4 deletions
diff --git a/src/api/Server.ts b/src/api/Server.ts index e92335a5..560014d0 100644 --- a/src/api/Server.ts +++ b/src/api/Server.ts @@ -11,6 +11,7 @@ import { initRateLimits } from "./middlewares/RateLimit"; import TestClient from "./middlewares/TestClient"; import { initTranslation } from "./middlewares/Translation"; import { initInstance } from "./util/handlers/Instance"; +import fs from "fs"; export interface FosscordServerOptions extends ServerOptions {} @@ -42,6 +43,8 @@ export class FosscordServer extends Server { this.app.use( morgan("combined", { skip: (req, res) => { + if(req.path.endsWith(".map")) return true; + if(req.path.includes("/assets/") && !fs.existsSync(path.join(__dirname, "..", "..", "..", "assets", req.path.split("/")[0].split('?')[0]))) return true; let skip = !(process.env["LOG_REQUESTS"]?.includes(res.statusCode.toString()) ?? false); if (process.env["LOG_REQUESTS"]?.charAt(0) == "-") skip = !skip; return skip; diff --git a/src/api/middlewares/TestClient.ts b/src/api/middlewares/TestClient.ts index 3afd0339..9090840e 100644 --- a/src/api/middlewares/TestClient.ts +++ b/src/api/middlewares/TestClient.ts @@ -6,7 +6,9 @@ import path from "path"; import { green } from "picocolors"; import ProxyAgent from "proxy-agent"; import { AssetCacheItem } from "../util/entities/AssetCacheItem"; +import { patchFile } from ".."; +const prettier = require("prettier"); const AssetsPath = path.join(__dirname, "..", "..", "..", "assets"); export default function TestClient(app: Application) { @@ -39,7 +41,7 @@ export default function TestClient(app: Application) { let response: FetchResponse; let buffer: Buffer; let assetCacheItem: AssetCacheItem = new AssetCacheItem(req.params.file); - if (newAssetCache.has(req.params.file)) { + if (newAssetCache.has(req.params.file) && fs.existsSync(newAssetCache.get(req.params.file)!.FilePath)) { assetCacheItem = newAssetCache.get(req.params.file)!; assetCacheItem.Headers.forEach((value: any, name: any) => { res.set(name, value); @@ -56,16 +58,21 @@ export default function TestClient(app: Application) { ...req.headers } }); - //set cache info assetCacheItem.Headers = Object.fromEntries(stripHeaders(response.headers)); - assetCacheItem.FilePath = path.join(assetCacheDir, req.params.file); assetCacheItem.Key = req.params.file; //add to cache and save newAssetCache.set(req.params.file, assetCacheItem); + + if(response.status != 200) { + return res.status(404).send("Not found"); + } + assetCacheItem.FilePath = path.join(assetCacheDir, req.params.file); + if(!fs.existsSync(assetCacheDir)) + fs.mkdirSync(assetCacheDir); fs.writeFileSync(path.join(assetCacheDir, "index.json"), JSON.stringify(Object.fromEntries(newAssetCache), null, 4)); //download file - fs.writeFileSync(assetCacheItem.FilePath, await response.buffer()); + fs.writeFileSync(assetCacheItem.FilePath, /.*\.(js|css)/.test(req.params.file) ? patchFile(assetCacheItem.FilePath, (await response.buffer()).toString()) : await response.buffer()); } assetCacheItem.Headers.forEach((value: string, name: string) => { diff --git a/src/api/util/TestClientPatcher.ts b/src/api/util/TestClientPatcher.ts new file mode 100644 index 00000000..2e9bfafe --- /dev/null +++ b/src/api/util/TestClientPatcher.ts @@ -0,0 +1,107 @@ +import path from "path"; +import fs from "fs"; + +console.log('[TestClient] Loading private assets...'); + +const privateAssetsRoot = path.join(__dirname, "..", "..", "..", "assets", "private"); +const iconsRoot = path.join(privateAssetsRoot, "icons"); +const icons = new Map<string, Buffer>(); + +fs.readdirSync(iconsRoot).forEach(file => { + const fileName = path.basename(file); + //check if dir + if(fs.lstatSync(path.join(iconsRoot, file)).isDirectory()){ + return; + } + icons.set(fileName,fs.readFileSync(path.join(iconsRoot,file)) as Buffer); +}); + +fs.readdirSync(path.join(iconsRoot, "custom")).forEach(file => { + const fileName = path.basename(file); + if(fs.lstatSync(path.join(iconsRoot,"custom", file)).isDirectory()){ + return; + } + icons.set(fileName,fs.readFileSync(path.join(iconsRoot,"custom",file)) as Buffer); +}); + +console.log('[TestClient] Patcher ready!'); + +export function patchFile(filePath: string, content: string): string { + console.log(`[TestClient] Patching ${filePath}`); + let startTime = Date.now(); + + content = prettier(filePath, content); + content = autoPatch(filePath, content); + + console.log(`[TestClient] Patched ${filePath} in ${Date.now() - startTime}ms`); + return content; +} +function prettier(filePath: string, content: string): string{ + let prettier = require("prettier"); + let parser; + filePath = filePath.toLowerCase().split('?')[0]; + if(filePath.endsWith(".js")) { + parser = "babel"; + } else if (filePath.endsWith(".ts")){ + parser = "typescript"; + } else if(filePath.endsWith(".css")){ + parser = "css"; + } else if(filePath.endsWith(".json")){ + parser = "json"; + } + else { + console.log(`[TestClient] Skipping prettier for ${filePath}, unknown file type!`); + return content; + } + content = prettier.format(content, { + tabWidth: 4, + useTabs: true, + printWidth: 140, + trailingComma: "none", + parser + }); + console.log(`[TestClient] Prettified ${filePath}!`); + return content; +} + +function autoPatch(filePath: string, content: string): string{ + //remove nitro references + content = content.replace(/Discord Nitro/g, "Fosscord Premium"); + content = content.replace(/"Nitro"/g, "\"Premium\""); + content = content.replace(/Nitro /g, "Premium "); + content = content.replace(/ Nitro/g, " Premium"); + content = content.replace(/\[Nitro\]/g, "[Premium]"); + content = content.replace(/\*Nitro\*/g, "*Premium*"); + content = content.replace(/\"Nitro \. /g, "\"Premium. "); + + //remove discord references + content = content.replace(/ Discord /g, " Fosscord "); + content = content.replace(/Discord /g, "Fosscord "); + content = content.replace(/ Discord/g, " Fosscord"); + content = content.replace(/Discord Premium/g, "Fosscord Premium"); + content = content.replace(/Discord Nitro/g, "Fosscord Premium"); + content = content.replace(/Discord's/g, "Fosscord's"); + //content = content.replace(/DiscordTag/g, "FosscordTag"); + content = content.replace(/\*Discord\*/g, "*Fosscord*"); + + //change some vars + content = content.replace('dsn: "https://fa97a90475514c03a42f80cd36d147c4@sentry.io/140984"', "dsn: (/true/.test(localStorage.sentryOptIn)?'https://6bad92b0175d41a18a037a73d0cff282@sentry.thearcanebrony.net/12':'')"); + content = content.replace('t.DSN = "https://fa97a90475514c03a42f80cd36d147c4@sentry.io/140984"', "t.DSN = (/true/.test(localStorage.sentryOptIn)?'https://6bad92b0175d41a18a037a73d0cff282@sentry.thearcanebrony.net/12':'')"); + content = content.replace('--brand-experiment: hsl(235, calc(var(--saturation-factor, 1) * 85.6%), 64.7%);', '--brand-experiment: hsl(var(--brand-hue), calc(var(--saturation-factor, 1) * 85.6%), 50%);'); + content = content.replaceAll(/--brand-experiment-(\d{1,4}): hsl\(235/g, '--brand-experiment-\$1: hsl(var(--brand-hue)') + + //logos + content = content.replace(/d: "M23\.0212.*/, `d: "${icons.get("homeIcon.path")!.toString()}"`); + content = content.replace('width: n, height: o, viewBox: "0 0 28 20"', 'width: 48, height: 48, viewBox: "0 0 48 48"'); + + //undo webpacking + // - booleans + content = content.replace(/!0/g, "true"); + content = content.replace(/!1/g, "false"); + // - real esmodule defs + content = content.replace(/Object.defineProperty\((.), "__esModule", { value: (.*) }\);/g, '\$1.__esModule = \$2;'); + + + console.log(`[TestClient] Autopatched ${path.basename(filePath)}!`); + return content; +} \ No newline at end of file diff --git a/src/api/util/index.ts b/src/api/util/index.ts index d06860cd..f01c2f43 100644 --- a/src/api/util/index.ts +++ b/src/api/util/index.ts @@ -8,3 +8,5 @@ export * from "./utility/ipAddress"; export * from "./utility/passwordStrength"; export * from "./utility/RandomInviteID"; export * from "./utility/String"; +export * from "./utility/captcha"; +export * from "./TestClientPatcher"; \ No newline at end of file |