mirror of
https://github.com/spacebarchat/server.git
synced 2024-11-22 02:12:40 +01:00
Basic client patching system
This commit is contained in:
parent
58111e9df4
commit
09b5e9c081
2
.gitignore
vendored
2
.gitignore
vendored
@ -32,3 +32,5 @@ yarn.lock
|
||||
dbconf.json
|
||||
|
||||
migrations.db
|
||||
|
||||
assets/cache_src/
|
||||
|
@ -1,68 +0,0 @@
|
||||
/* replace tos acceptance popup */
|
||||
#app-mount > div:nth-child(7) > div > div > div.tooltipContent-bqVLWK {
|
||||
visibility: hidden;
|
||||
}
|
||||
#app-mount > div:nth-child(7) > div > div > div.tooltipContent-bqVLWK::after {
|
||||
visibility: visible;
|
||||
display: block;
|
||||
content: "You need to agree to this instance's rules to continue";
|
||||
margin-top: -32px;
|
||||
}
|
||||
/* replace login header */
|
||||
#app-mount > div.app-1q1i1E > div > div > div > div > form > div > div > div.mainLoginContainer-1ddwnR > h3 {
|
||||
visibility: hidden;
|
||||
}
|
||||
h3.title-jXR8lp.marginBottom8-AtZOdT.base-1x0h_U.size24-RIRrxO::after {
|
||||
margin-top: -32px;
|
||||
content: "Welcome to Fosscord!";
|
||||
visibility: visible;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Logo in top left when bg removed */
|
||||
#app-mount > div.app-1q1i1E > div > a {
|
||||
/* replace me: original dimensions: 130x36 */
|
||||
background: url(https://raw.githubusercontent.com/fosscord/fosscord/master/assets-rebrand/svg/Fosscord-Wordmark-Gradient.svg);
|
||||
width: 130px;
|
||||
height: 23px;
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
/* replace TOS text */
|
||||
|
||||
#app-mount
|
||||
> div.app-1q1i1E
|
||||
> div
|
||||
> div
|
||||
> div
|
||||
> form
|
||||
> div
|
||||
> div
|
||||
> div.flex-1xMQg5.flex-1O1GKY.horizontal-1ae9ci.horizontal-2EEEnY.flex-1O1GKY.directionRow-3v3tfG.justifyStart-2NDFzi.alignCenter-1dQNNs.noWrap-3jynv6.marginTop20-3TxNs6
|
||||
> label
|
||||
> div.label-cywgfr.labelClickable-11AuB8.labelForward-1wfipV
|
||||
> * {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#app-mount
|
||||
> div.app-1q1i1E
|
||||
> div
|
||||
> div
|
||||
> div
|
||||
> form
|
||||
> div
|
||||
> div
|
||||
> div.flex-1xMQg5.flex-1O1GKY.horizontal-1ae9ci.horizontal-2EEEnY.flex-1O1GKY.directionRow-3v3tfG.justifyStart-2NDFzi.alignCenter-1dQNNs.noWrap-3jynv6.marginTop20-3TxNs6
|
||||
> label
|
||||
> div.label-cywgfr.labelClickable-11AuB8.labelForward-1wfipV::after {
|
||||
visibility: visible;
|
||||
content: "I have read and agree with the rules set by this instance.";
|
||||
display: block;
|
||||
margin-top: -16px;
|
||||
}
|
||||
|
||||
/* shrink login box to same size as register */
|
||||
.authBoxExpanded-2jqaBe {
|
||||
width: 480px !important;
|
||||
}
|
@ -1,92 +1,4 @@
|
||||
/* loading spinner */
|
||||
#app-mount > div.app-1q1i1E > div.container-16j22k.fixClipping-3qAKRb > div.content-1-zrf2 > video {
|
||||
filter: opacity(1);
|
||||
background: url("http://www.clipartbest.com/cliparts/7ca/6Rr/7ca6RrLAi.gif");
|
||||
background-size: contain;
|
||||
/* width: 64px;
|
||||
height: 64px; */
|
||||
padding-bottom: 64px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
/* home button icon */
|
||||
#app-mount
|
||||
> div.app-1q1i1E
|
||||
> div
|
||||
> div.layers-3iHuyZ.layers-3q14ss
|
||||
> div
|
||||
> div
|
||||
> nav
|
||||
> ul
|
||||
> div.scroller-1Bvpku.none-2Eo-qx.scrollerBase-289Jih
|
||||
> div.tutorialContainer-2sGCg9
|
||||
> div
|
||||
> div.listItemWrapper-KhRmzM
|
||||
> div
|
||||
> svg
|
||||
> foreignObject
|
||||
> div
|
||||
> div {
|
||||
background-image: url(https://raw.githubusercontent.com/fosscord/fosscord/master/assets-rebrand/svg/Fosscord-Icon-Rounded-Subtract.svg);
|
||||
background-size: contain;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
#app-mount
|
||||
> div.app-1q1i1E
|
||||
> div
|
||||
> div.layers-3iHuyZ.layers-3q14ss
|
||||
> div
|
||||
> div
|
||||
> nav
|
||||
> ul
|
||||
> div.scroller-1Bvpku.none-2Eo-qx.scrollerBase-289Jih
|
||||
> div.tutorialContainer-2sGCg9
|
||||
> div
|
||||
> div.listItemWrapper-KhRmzM
|
||||
> div
|
||||
> svg
|
||||
> foreignObject
|
||||
> div
|
||||
> div,
|
||||
#app-mount
|
||||
> div.app-1q1i1E
|
||||
> div
|
||||
> div.layers-3iHuyZ.layers-3q14ss
|
||||
> div
|
||||
> div
|
||||
> nav
|
||||
> ul
|
||||
> div.scroller-1Bvpku.none-2Eo-qx.scrollerBase-289Jih
|
||||
> div.tutorialContainer-2sGCg9
|
||||
> div
|
||||
> div.listItemWrapper-KhRmzM
|
||||
> div
|
||||
> svg
|
||||
> foreignObject
|
||||
> div
|
||||
> div:hover {
|
||||
background-color: white;
|
||||
}
|
||||
/* Login QR */
|
||||
#app-mount > div.app-1q1i1E > div > div > div > div > form > div > div > div.transitionGroup-aR7y1d.qrLogin-1AOZMt,
|
||||
#app-mount > div.app-1q1i1E > div > div > div > div > form > div > div > div.verticalSeparator-3huAjp,
|
||||
/* Remove login bg */
|
||||
#app-mount > div.app-1q1i1E > div > svg,
|
||||
/* Download bar */
|
||||
#app-mount > div.app-1q1i1E > div > div.layers-3iHuyZ.layers-3q14ss > div > div > div > div.notice-3bPHh-.colorDefault-22HBa0,
|
||||
/* Connection problem links */
|
||||
#app-mount > div.app-1q1i1E > div.container-16j22k.fixClipping-3qAKRb > div.problems-3mgf6w.slideIn-sCvzGz > div:nth-child(2),
|
||||
/* Downloads button */
|
||||
#app-mount > div.app-1q1i1E > div > div.layers-3iHuyZ.layers-3q14ss > div > div > nav > ul > div.scroller-1Bvpku.none-2Eo-qx.scrollerBase-289Jih > div:nth-child(7) > div.listItemWrapper-KhRmzM > div > svg > foreignObject > div,
|
||||
#app-mount > div.app-1q1i1E > div > div.layers-3iHuyZ.layers-3q14ss > div > div > nav > ul > div.scroller-1Bvpku.none-2Eo-qx.scrollerBase-289Jih > div:nth-child(6) > div,
|
||||
/* help button */
|
||||
#app-mount > div.app-1q1i1E > div > div.layers-3iHuyZ.layers-3q14ss > div > div > div > div.content-98HsJk > div.chat-3bRxxu > section > div.toolbar-1t6TWx > a,
|
||||
/* download button start of guild */
|
||||
#chat-messages-899316648933185083 > div > div > div:nth-child(5),
|
||||
/* Thread permissions etc popups */
|
||||
#app-mount > div.app-1q1i1E > div > div.layers-3iHuyZ.layers-3q14ss > div > div > div > div.content-98HsJk > div.sidebar-2K8pFh.hasNotice-1XRy4h > nav > div.container-3O_wAf,
|
||||
/* home button icon */
|
||||
#app-mount > div.app-1q1i1E > div > div.layers-3iHuyZ.layers-3q14ss > div > div > nav > ul > div.scroller-1Bvpku.none-2Eo-qx.scrollerBase-289Jih > div.tutorialContainer-2sGCg9 > div > div.listItemWrapper-KhRmzM > div > svg > foreignObject > div > div > svg {
|
||||
display: none;
|
||||
}
|
||||
:root {
|
||||
--brand-hue: 22;
|
||||
}
|
@ -5,7 +5,6 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Discord Test Client</title>
|
||||
<link rel="stylesheet" href="/assets/fosscord.css" />
|
||||
<link id="logincss" rel="stylesheet" href="/assets/fosscord-login.css" />
|
||||
<link id="customcss" rel="stylesheet" href="/assets/user.css" />
|
||||
<!-- inline plugin marker -->
|
||||
<!-- preload plugin marker -->
|
||||
@ -28,20 +27,21 @@
|
||||
INVITE_HOST: `${location.hostname}/invite`,
|
||||
GUILD_TEMPLATE_HOST: "${location.host}",
|
||||
GIFT_CODE_HOST: "${location.hostname}",
|
||||
RELEASE_CHANNEL: "stable",
|
||||
MARKETING_ENDPOINT: "//discord.com",
|
||||
BRAINTREE_KEY: "production_5st77rrc_49pp2rp4phym7387",
|
||||
STRIPE_KEY: "pk_live_CUQtlpQUF0vufWpnpUmQvcdi",
|
||||
NETWORKING_ENDPOINT: "//router.discordapp.net",
|
||||
RTC_LATENCY_ENDPOINT: "//${location.hostname}/rtc",
|
||||
ACTIVITY_APPLICATION_HOST: "discordsays.com",
|
||||
PROJECT_ENV: "production",
|
||||
REMOTE_AUTH_ENDPOINT: "//localhost:3020",
|
||||
SENTRY_TAGS: { buildId: "75e36d9", buildType: "normal" },
|
||||
MIGRATION_SOURCE_ORIGIN: "https://${location.hostname}",
|
||||
MIGRATION_DESTINATION_ORIGIN: "https://${location.hostname}",
|
||||
HTML_TIMESTAMP: Date.now(),
|
||||
ALGOLIA_KEY: "aca0d7082e4e63af5ba5917d5e96bed0"
|
||||
ALGOLIA_KEY: "aca0d7082e4e63af5ba5917d5e96bed0",
|
||||
SENTRY_TAGS: { instance: document.location.host },
|
||||
PROJECT_ENV: "development",
|
||||
RELEASE_CHANNEL: "staging",
|
||||
};
|
||||
GLOBAL_ENV.MEDIA_PROXY_ENDPOINT = location.protocol + "//" + GLOBAL_ENV.CDN_HOST;
|
||||
const localStorage = window.localStorage;
|
||||
|
0
assets/private/icons/custom/.gitkeep
Normal file
0
assets/private/icons/custom/.gitkeep
Normal file
1
assets/private/icons/homeIcon.path
Normal file
1
assets/private/icons/homeIcon.path
Normal file
@ -0,0 +1 @@
|
||||
M 0,0 47.999993,2.7036528e-4 C 48.001796,3.3028172 47.663993,6.5968018 46.991821,9.8301938 43.116101,28.454191 28.452575,43.116441 9.8293509,46.992163 6.5960834,47.664163 3.3023222,48.001868 0,47.999992 Z m 9.8293509,28.735114 v 9.248482 C 22.673599,33.047696 32.857154,22.749268 37.63852,9.829938 H 9.8293509 v 8.679899 H 22.931288 c -3.554489,3.93617 -7.735383,7.257633 -12.373436,9.829938 -0.241031,0.133684 -0.483864,0.265492 -0.7285011,0.395339 z
|
@ -16,6 +16,8 @@
|
||||
"settings": {
|
||||
"files.exclude": {
|
||||
"*.ansi": true,
|
||||
"**/cache": true,
|
||||
"**/cache_src": true
|
||||
}
|
||||
},
|
||||
"launch": {
|
||||
@ -32,6 +34,12 @@
|
||||
"name": "Run Fosscord with debugger (kitty)",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "[ \"$(basename $PWD)\" != \"fosscord-server\" ] && cd ..; $(ps -o comm= $PPID) assets/cache",
|
||||
"name": "Open testclient patch workspace",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
24
scripts/patches/applyPatches.js
Normal file
24
scripts/patches/applyPatches.js
Normal file
@ -0,0 +1,24 @@
|
||||
const { execSync } = require("child_process");
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const { argv, stdout, exit } = require("process");
|
||||
const { execIn, parts, getDirs, walk, sanitizeVarName } = require("../utils");
|
||||
|
||||
//apply patches
|
||||
const patchDir = path.join(__dirname, "..", "..", "assets", "testclient_patches");
|
||||
const targetDir = path.join(__dirname, "..", "..", "assets", "cache");
|
||||
const files = fs.readdirSync(patchDir);
|
||||
files.forEach((file) => {
|
||||
const filePath = path.join(patchDir, file);
|
||||
const stats = fs.statSync(filePath);
|
||||
if (stats.isFile()) {
|
||||
const ext = path.extname(file);
|
||||
if (ext === ".patch") {
|
||||
execSync(`git apply ${filePath}`, {
|
||||
cwd: targetDir,
|
||||
maxBuffer: 1024 * 1024 * 10,
|
||||
});
|
||||
console.log(`Applied patch ${file} to ${newFilePath}`);
|
||||
}
|
||||
}
|
||||
});
|
40
scripts/patches/mkPatches.js
Normal file
40
scripts/patches/mkPatches.js
Normal file
@ -0,0 +1,40 @@
|
||||
const { execSync } = require("child_process");
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const { argv, stdout, exit } = require("process");
|
||||
const { execIn, parts, getDirs, walk, sanitizeVarName } = require("../utils");
|
||||
|
||||
//generate git patch for each file in assets/cache
|
||||
const srcDir = path.join(__dirname, "..", "..", "assets", "cache");
|
||||
const destDir = path.join(__dirname, "..", "..", "assets", "cache_src");
|
||||
const patchDir = path.join(__dirname, "..", "..", "assets", "testclient_patches");
|
||||
if(!fs.existsSync(patchDir)) fs.mkdirSync(patchDir);
|
||||
const files = fs.readdirSync(srcDir);
|
||||
files.forEach((file) => {
|
||||
const filePath = path.join(srcDir, file);
|
||||
const stats = fs.statSync(filePath);
|
||||
if (stats.isFile()) {
|
||||
const ext = path.extname(file);
|
||||
if (ext === ".js" || ext === ".css") {
|
||||
const newFilePath = path.join(destDir, file);
|
||||
//check if file has been modified
|
||||
let patch;
|
||||
try {
|
||||
let es = execSync(`diff -du --speed-large-files --horizon-lines=0 ${newFilePath} ${filePath}`, {
|
||||
maxBuffer: 1024 * 1024 * 10,
|
||||
}).toString();
|
||||
patch="";
|
||||
} catch (e) {
|
||||
patch = e.stdout.toString().replaceAll(path.join(destDir, file), file).replaceAll(path.join(srcDir, file), file);
|
||||
}
|
||||
if (patch.length > 0) {
|
||||
//generate patch;
|
||||
fs.writeFileSync(path.join(patchDir, file + ".patch"), patch);
|
||||
console.log(`Generated patch for ${file}: ${patch.length} bytes, ${patch.split("\n").length} lines, ${patch.split("\n").filter((x) => x.startsWith("+")).length} additions, ${patch.split("\n").filter((x) => x.startsWith("-")).length} deletions`);
|
||||
}
|
||||
else {
|
||||
//console.log(`No changes for ${file}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
75
scripts/patches/prepWS.js
Normal file
75
scripts/patches/prepWS.js
Normal file
@ -0,0 +1,75 @@
|
||||
const { execSync } = require("child_process");
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const { argv, stdout, exit } = require("process");
|
||||
const { execIn, parts, getDirs, walk, sanitizeVarName } = require("../utils");
|
||||
|
||||
//copy all js and css files from assets/cache to assets/dist
|
||||
const srcDir = path.join(__dirname, "..", "..", "assets", "cache");
|
||||
const destDir = path.join(__dirname, "..", "..", "assets", "cache_src");
|
||||
if(!fs.existsSync(destDir)) fs.mkdirSync(destDir);
|
||||
const files = fs.readdirSync(srcDir);
|
||||
files.forEach((file) => {
|
||||
const filePath = path.join(srcDir, file);
|
||||
const stats = fs.statSync(filePath);
|
||||
if (stats.isFile()) {
|
||||
const ext = path.extname(file);
|
||||
if (ext === ".js" || ext === ".css") {
|
||||
const newFilePath = path.join(destDir, file);
|
||||
if(!fs.existsSync(newFilePath)) {
|
||||
fs.copyFileSync(filePath, newFilePath);
|
||||
console.log(`Copied ${file} to ${newFilePath}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if(!fs.existsSync(path.join(srcDir, ".vscode"))) fs.mkdirSync(path.join(srcDir, ".vscode"));
|
||||
fs.writeFileSync(path.join(srcDir, ".vscode", "settings.json"), JSON.stringify({
|
||||
"codemetrics.basics.DecorationModeEnabled": false,
|
||||
"codemetrics.basics.CodeLensEnabled": false,
|
||||
"editor.codeLens": false,
|
||||
//"editor.minimap.enabled": false,
|
||||
"codemetrics.basics.MetricsForArrowFunctionsToggled": false,
|
||||
"codemetrics.basics.MetricsForClassDeclarationsToggled": false,
|
||||
"codemetrics.basics.MetricsForConstructorsToggled": false,
|
||||
"codemetrics.basics.MetricsForEnumDeclarationsToggled": false,
|
||||
"codemetrics.basics.MetricsForFunctionExpressionsToggled": false,
|
||||
"codemetrics.basics.MetricsForFunctionDeclarationsToggled": false,
|
||||
"codemetrics.basics.MetricsForMethodDeclarationsToggled": false,
|
||||
"codemetrics.basics.OverviewRulerModeEnabled": false,
|
||||
"editor.fontFamily": "'JetBrainsMono Nerd Font', 'JetBrainsMono', 'Droid Sans Mono', 'monospace', monospace",
|
||||
"editor.accessibilityPageSize": 1,
|
||||
"editor.accessibilitySupport": "off",
|
||||
"editor.autoClosingDelete": "never",
|
||||
//"editor.autoIndent": "none",
|
||||
//"editor.colorDecorators": false,
|
||||
"editor.comments.ignoreEmptyLines": false,
|
||||
"editor.copyWithSyntaxHighlighting": false,
|
||||
"editor.comments.insertSpace": false,
|
||||
"editor.detectIndentation": false,
|
||||
"editor.dragAndDrop": false,
|
||||
"editor.dropIntoEditor.enabled": false,
|
||||
"editor.experimental.pasteActions.enabled": false,
|
||||
"editor.guides.highlightActiveIndentation": false,
|
||||
"color-highlight.enable": false,
|
||||
"gitlens.blame.highlight.locations": [
|
||||
"gutter"
|
||||
],
|
||||
"todohighlight.isEnable": false,
|
||||
"todohighlight.maxFilesForSearch": 1,
|
||||
"editor.maxTokenizationLineLength": 1200,
|
||||
"editor.minimap.maxColumn": 140,
|
||||
"explorer.openEditors.visible": 0,
|
||||
"editor.fontLigatures": false,
|
||||
"files.exclude": {
|
||||
"*.mp3": true,
|
||||
"*.png": true,
|
||||
"*.svg": true,
|
||||
"*.webm": true,
|
||||
"*.webp": true,
|
||||
"*.woff2": true,
|
||||
"**/.vscode/": true
|
||||
},
|
||||
"editor.guides.bracketPairs": true
|
||||
}, null, 4));
|
||||
console.log(`Workspace prepared at ${srcDir}!`);
|
24
scripts/patches/resetWS.js
Normal file
24
scripts/patches/resetWS.js
Normal file
@ -0,0 +1,24 @@
|
||||
const { execSync } = require("child_process");
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const { argv, stdout, exit } = require("process");
|
||||
const { execIn, parts, getDirs, walk, sanitizeVarName } = require("../utils");
|
||||
|
||||
//copy all js and css files from assets/cache_src to assets/cache
|
||||
const srcDir = path.join(__dirname, "..", "..", "assets", "cache_src");
|
||||
const destDir = path.join(__dirname, "..", "..", "assets", "cache");
|
||||
if(!fs.existsSync(destDir)) fs.mkdirSync(destDir);
|
||||
const files = fs.readdirSync(srcDir);
|
||||
files.forEach((file) => {
|
||||
const filePath = path.join(srcDir, file);
|
||||
const stats = fs.statSync(filePath);
|
||||
if (stats.isFile()) {
|
||||
const ext = path.extname(file);
|
||||
if (ext === ".js" || ext === ".css") {
|
||||
const newFilePath = path.join(destDir, file);
|
||||
fs.rmSync(newFilePath);
|
||||
fs.copyFileSync(filePath, newFilePath);
|
||||
console.log(`Copied ${file} to ${newFilePath}`);
|
||||
}
|
||||
}
|
||||
});
|
@ -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;
|
||||
|
@ -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) => {
|
||||
|
107
src/api/util/TestClientPatcher.ts
Normal file
107
src/api/util/TestClientPatcher.ts
Normal file
@ -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;
|
||||
}
|
@ -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";
|
Loading…
Reference in New Issue
Block a user