diff --git a/ReferenceClientProxyImplementation/Resources/Assets/checkLocale.js b/ReferenceClientProxyImplementation/Resources/Assets/checkLocale.js
new file mode 100644
index 0000000..2f46120
--- /dev/null
+++ b/ReferenceClientProxyImplementation/Resources/Assets/checkLocale.js
@@ -0,0 +1,47 @@
+const localStorage = window.localStorage;
+// TODO: remote auth
+// window.GLOBAL_ENV.REMOTE_AUTH_ENDPOINT = window.GLOBAL_ENV.GATEWAY_ENDPOINT.replace(/wss?:/, "");
+localStorage.setItem("gatewayURL", window.GLOBAL_ENV.GATEWAY_ENDPOINT);
+localStorage.setItem(
+ "DeveloperOptionsStore",
+ `{"trace":false,"canary":false,"logGatewayEvents":true,"logOverlayEvents":true,"logAnalyticsEvents":true,"sourceMapsEnabled":false,"axeEnabled":false}`
+);
+
+const supportedLocales = [
+ "bg",
+ "cs",
+ "da",
+ "de",
+ "el",
+ "en-GB",
+ "es-ES",
+ "fi",
+ "fr",
+ "hi",
+ "hr",
+ "hu",
+ "it",
+ "ja",
+ "ko",
+ "lt",
+ "nl",
+ "no",
+ "pl",
+ "pt-BR",
+ "ro",
+ "ru",
+ "sv-SE",
+ "th",
+ "tr",
+ "uk",
+ "vi",
+ "zh-CN",
+ "zh-TW"
+];
+
+const settings = JSON.parse(localStorage.getItem("UserSettingsStore"));
+if (settings && !supportedLocales.includes(settings.locale)) {
+ // fix client locale wrong and client not loading at all
+ settings.locale = "en-US";
+ localStorage.setItem("UserSettingsStore", JSON.stringify(settings));
+}
\ No newline at end of file
diff --git a/ReferenceClientProxyImplementation/Resources/Assets/dff87c953f43b561d71fbcfe8a93a79a.png b/ReferenceClientProxyImplementation/Resources/Assets/dff87c953f43b561d71fbcfe8a93a79a.png
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ReferenceClientProxyImplementation/Resources/Assets/dff87c953f43b561d71fbcfe8a93a79a.png
diff --git a/ReferenceClientProxyImplementation/Resources/Assets/endpoints.json b/ReferenceClientProxyImplementation/Resources/Assets/endpoints.json
new file mode 100644
index 0000000..d5478e7
--- /dev/null
+++ b/ReferenceClientProxyImplementation/Resources/Assets/endpoints.json
@@ -0,0 +1,115 @@
+{
+ "USER_CHANNELS": "/users/@me/channels",
+ "USER_ACTIVITY_STATISTICS": "/users/@me/activities/statistics/applications",
+ "ACTIVITIES": "/activities",
+ "LOBBIES": "/lobbies",
+ "LOBBY_SEARCH": "/lobbies/search",
+ "NETWORKING_TOKEN": "/networking/token",
+ "USER_GAMES_NOTIFICATIONS": "/users/@me/settings/game-notifications",
+ "USER_GAMES_NOTIFICATIONS_OVERRIDES": "/users/@me/settings/game-notifications/overrides",
+ "UNVERIFIED_APPLICATIONS": "/unverified-applications",
+ "UNVERIFIED_APPLICATIONS_ICONS": "/unverified-applications/icons",
+ "BULK_ACK": "/read-states/ack-bulk",
+ "GUILDS": "/guilds",
+ "CHANNELS": "/channels",
+ "TUTORIAL_INDICATORS": "/tutorial/indicators",
+ "TUTORIAL_INDICATORS_SUPPRESS": "/tutorial/indicators/suppress",
+ "USERS": "/users",
+ "ME": "/users/@me",
+ "DELETE_ACCOUNT": "/users/@me/delete",
+ "DISABLE_ACCOUNT": "/users/@me/disable",
+ "DEVICES": "/users/@me/devices",
+ "SETTINGS": "/users/@me/settings",
+ "SETTINGS_CONSENT": "/users/@me/consent",
+ "PHONE": "/users/@me/phone",
+ "VERIFY_PHONE": "/users/@me/phone/verify",
+ "VERIFY_PHONE_NEW": "/phone-verifications/verify",
+ "RESEND_PHONE": "/phone-verifications/resend",
+ "CONNECTIONS": "/users/@me/connections",
+ "CONNECTION_SYNC_CONTACTS": "/users/@me/connections/contacts/@me/external-friend-list-entries",
+ "NOTES": "/users/@me/notes",
+ "MENTIONS": "/users/@me/mentions",
+ "CAPTCHA": "/users/@me/captcha/verify",
+ "EXPERIMENTS": "/experiments",
+ "LOGIN": "/auth/login",
+ "LOGIN_MFA": "/auth/mfa/totp",
+ "LOGIN_SMS": "/auth/mfa/sms",
+ "LOGIN_SMS_SEND": "/auth/mfa/sms/send",
+ "REMOTE_AUTH_INITIALIZE": "/users/@me/remote-auth",
+ "REMOTE_AUTH_CANCEL": "/users/@me/remote-auth/cancel",
+ "REMOTE_AUTH_FINISH": "/users/@me/remote-auth/finish",
+ "LOGOUT": "/auth/logout",
+ "REGISTER": "/auth/register",
+ "REGISTER_PHONE": "/auth/register/phone",
+ "TRACK": "/science",
+ "SSO": "/sso",
+ "VERIFY": "/auth/verify",
+ "AUTHORIZE_IP": "/auth/authorize-ip",
+ "VERIFY_RESEND": "/auth/verify/resend",
+ "FORGOT_PASSWORD": "/auth/forgot",
+ "RESET_PASSWORD": "/auth/reset",
+ "ICE": "/voice/ice",
+ "REPORT": "/report",
+ "REPORT_V2": "/reports",
+ "REPORT_OPTIONS": "/report/options",
+ "INTEGRATIONS": "/integrations",
+ "GATEWAY": "/gateway",
+ "APPLICATIONS_DETECTABLE": "/applications/detectable",
+ "OAUTH2_AUTHORIZE": "/oauth2/authorize",
+ "OAUTH2_AUTHORIZE_WEBHOOK_CHANNELS": "/oauth2/authorize/webhook-channels",
+ "OAUTH2_CURRENT_AUTH": "/oauth2/@me",
+ "OAUTH2_TOKENS": "/oauth2/tokens",
+ "OAUTH2_WHITELIST_ACCEPT": "/oauth2/whitelist/accept",
+ "MFA_TOTP_ENABLE": "/users/@me/mfa/totp/enable",
+ "MFA_TOTP_DISABLE": "/users/@me/mfa/totp/disable",
+ "MFA_SMS_ENABLE": "/users/@me/mfa/sms/enable",
+ "MFA_SMS_DISABLE": "/users/@me/mfa/sms/disable",
+ "MFA_CODES": "/users/@me/mfa/codes",
+ "DISABLE_EMAIL_NOTIFICATIONS": "/users/disable-email-notifications",
+ "GUILD_PREMIUM_SUBSCRIPTION_COOLDOWN": "/users/@me/guilds/premium/subscriptions/cooldown",
+ "USER_GUILD_PREMIUM_SUBSCRIPTIONS": "/users/@me/guilds/premium/subscriptions",
+ "USER_PREMIUM_GUILD_SUBSCRIPTION_SLOTS": "/users/@me/guilds/premium/subscription-slots",
+ "BILLING_STRIPE_SETUP_INTENT_SECRET": "/users/@me/billing/stripe/setup-intents",
+ "BILLING_PAYMENT_SOURCES": "/users/@me/billing/payment-sources",
+ "BILLING_PAYMENTS": "/users/@me/billing/payments",
+ "BILLING_BRAINTREE_POPUP_BRIDGE": "/billing/braintree/popup-bridge",
+ "BILLING_BRAINTREE_POPUP_BRIDGE_CALLBACK": "/billing/braintree/popup-bridge/callback",
+ "BILLING_SUBSCRIPTIONS": "/users/@me/billing/subscriptions",
+ "BILLING_APPLY_APPLE_RECEIPT": "/billing/apple/apply-receipt",
+ "BILLING_INVOICE_PREVIEW": "/users/@me/billing/invoices/preview",
+ "USER_AGREEMENTS": "/users/@me/agreements",
+ "HANDOFF": "/auth/handoff",
+ "HANDOFF_EXCHANGE": "/auth/handoff/exchange",
+ "LIBRARY": "/users/@me/library",
+ "AUTH_CONSENT_REQUIRED": "/auth/consent-required",
+ "USER_HARVEST": "/users/@me/harvest",
+ "APPLICATION_BRANCHES": "/branches",
+ "APPLICATIONS_PUBLIC": "/applications/public",
+ "APPLICATIONS_TRENDING": "/applications/trending/global",
+ "STORE_PUBLISHED_LISTINGS_APPLICATIONS": "/store/published-listings/applications",
+ "STORE_PUBLISHED_LISTINGS_SKUS": "/store/published-listings/skus",
+ "ENTITLEMENTS_GIFTABLE": "/users/@me/entitlements/gifts",
+ "PROMOTIONS": "/promotions",
+ "PROMOTION_ACK": "/promotions/ack",
+ "HYPESQUAD_ONLINE": "/hypesquad/online",
+ "GIFS_SEARCH": "/gifs/search",
+ "GIFS_TRENDING": "/gifs/trending",
+ "GIFS_TRENDING_GIFS": "/gifs/trending-gifs",
+ "GIFS_SELECT": "/gifs/select",
+ "GIFS_SUGGEST": "/gifs/suggest",
+ "GIFS_TRENDING_SEARCH": "/gifs/trending-search",
+ "USER_GIFT_CODE_CREATE": "/users/@me/entitlements/gift-codes",
+ "USER_GIFT_CODES": "/users/@me/entitlements/gift-codes",
+ "GUILD_DISCOVERY": "/discoverable-guilds",
+ "GUILD_DISCOVERY_CATEGORIES": "/discovery/categories",
+ "GUILD_DISCOVERY_VALID_TERM": "/discovery/valid-term",
+ "USER_AFFINITIES": "/users/@me/affinities/users",
+ "GUILD_AFFINITIES": "/users/@me/affinities/guilds",
+ "XBOX_GAME_PASS_PROMOTION": "/promotions/xbox-game-pass",
+ "XBOX_GAME_PASS_PROMOTION_REDEEM": "/promotions/xbox-game-pass/redeem",
+ "FUNIMATION_PROMOTION": "/promotions/funimation",
+ "PARTNERS_CONNECTIONS": "/partners/connections",
+ "PARTNERS_APPLY": "/partners/apply",
+ "USER_STICKER_PACKS": "/users/@me/sticker-packs",
+ "INTERACTIONS": "/interactions"
+}
diff --git a/ReferenceClientProxyImplementation/Resources/Assets/features.json b/ReferenceClientProxyImplementation/Resources/Assets/features.json
new file mode 100644
index 0000000..1e1ebb1
--- /dev/null
+++ b/ReferenceClientProxyImplementation/Resources/Assets/features.json
@@ -0,0 +1,26 @@
+[
+ "ANIMATED_ICON",
+ "BANNER",
+ "COMMERCE",
+ "COMMUNITY",
+ "DISCOVERABLE",
+ "DISCOVERABLE_DISABLED",
+ "ENABLED_DISCOVERABLE_BEFORE",
+ "HUB",
+ "INVITE_SPLASH",
+ "MONETIZATION_ENABLED",
+ "MORE_EMOJI",
+ "MORE_STICKERS",
+ "NEWS",
+ "PARTNERED",
+ "PREVIEW_ENABLED",
+ "PRIVATE_THREADS",
+ "SEVEN_DAY_THREAD_ARCHIVE",
+ "THREE_DAY_THREAD_ARCHIVE",
+ "THREADS_ENABLED",
+ "TICKETED_EVENTS_ENABLED",
+ "VANITY_URL",
+ "VERIFIED",
+ "VIP_REGIONS",
+ "WELCOME_SCREEN_ENABLED"
+]
diff --git a/ReferenceClientProxyImplementation/Resources/Assets/fosscord-login.css b/ReferenceClientProxyImplementation/Resources/Assets/fosscord-login.css
new file mode 100644
index 0000000..37bb111
--- /dev/null
+++ b/ReferenceClientProxyImplementation/Resources/Assets/fosscord-login.css
@@ -0,0 +1,71 @@
+/* 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 Spacebar!";
+ 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/Spacebar-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;
+}
diff --git a/ReferenceClientProxyImplementation/Resources/Assets/fosscord.css b/ReferenceClientProxyImplementation/Resources/Assets/fosscord.css
new file mode 100644
index 0000000..283c29f
--- /dev/null
+++ b/ReferenceClientProxyImplementation/Resources/Assets/fosscord.css
@@ -0,0 +1,44 @@
+/* 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/Spacebar-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;
+}
\ No newline at end of file
diff --git a/ReferenceClientProxyImplementation/Resources/Assets/plugins/.gitkeep b/ReferenceClientProxyImplementation/Resources/Assets/plugins/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ReferenceClientProxyImplementation/Resources/Assets/plugins/.gitkeep
diff --git a/ReferenceClientProxyImplementation/Resources/Assets/preload-plugins/autoRegister.js b/ReferenceClientProxyImplementation/Resources/Assets/preload-plugins/autoRegister.js
new file mode 100644
index 0000000..15ef582
--- /dev/null
+++ b/ReferenceClientProxyImplementation/Resources/Assets/preload-plugins/autoRegister.js
@@ -0,0 +1,62 @@
+// Auto register guest account:
+const prefix = [
+ "mysterious",
+ "adventurous",
+ "courageous",
+ "precious",
+ "cynical",
+ "flamer ",
+ "despicable",
+ "suspicious",
+ "gorgeous",
+ "impeccable",
+ "lovely",
+ "stunning",
+ "keyed",
+ "phoned",
+ "glorious",
+ "amazing",
+ "strange",
+ "arcane"
+];
+const suffix = [
+ "Anonymous",
+ "Boy",
+ "Lurker",
+ "Keyhitter",
+ "User",
+ "Enjoyer",
+ "Hunk",
+ "Coolstar",
+ "Wrestling",
+ "TylerTheCreator",
+ "Ad",
+ "Gamer",
+ "Games",
+ "Programmer"
+];
+
+Array.prototype.random = function () {
+ return this[Math.floor(Math.random() * this.length)];
+};
+
+function _generateName() {
+ return `${prefix.random()}${suffix.random()}`;
+}
+
+var token = JSON.parse(localStorage.getItem("token"));
+if (!token && location.pathname !== "/login" && location.pathname !== "/register") {
+ fetch(`${window.GLOBAL_ENV.API_ENDPOINT}/auth/register`, {
+ method: "POST",
+ headers: {"content-type": "application/json"},
+ body: JSON.stringify({username: `${_generateName()}`, consent: true}) //${Date.now().toString().slice(-4)}
+ })
+ .then((x) => x.json())
+ .then((x) => {
+ localStorage.setItem("token", `"${x.token}"`);
+ if (!window.localStorage) {
+ // client already loaded -> need to reload to apply the newly registered user token
+ location.reload();
+ }
+ });
+}
diff --git a/ReferenceClientProxyImplementation/Resources/Assets/tools/rightsCalculator.js b/ReferenceClientProxyImplementation/Resources/Assets/tools/rightsCalculator.js
new file mode 100644
index 0000000..c324891
--- /dev/null
+++ b/ReferenceClientProxyImplementation/Resources/Assets/tools/rightsCalculator.js
@@ -0,0 +1,17 @@
+String.prototype.replaceAt = function (index, replacement) {
+ return this.substring(0, index) + replacement + this.substring(index + 1);
+}
+
+var legacyRights = 0n;
+var modernRights = '0'.repeat(document.getElementsByTagName("input").length);
+var configRights = {};
+
+function calculate(a) {
+ console.log(a)
+ legacyRights += a.checked ? (1n << BigInt(a.value)) : -(1n << BigInt(a.value))
+ modernRights = modernRights.replaceAt(a.value, a.checked ? '1' : '0')
+ configRights[a.name] = a.checked
+ document.getElementById("legacyRights").innerText = "Legacy rights (fosscord-server-ts): " + legacyRights
+ document.getElementById("modernRights").innerText = "User rights: " + modernRights
+ document.getElementById("configRights").value = JSON.stringify(configRights, null, 4)
+}
\ No newline at end of file
diff --git a/ReferenceClientProxyImplementation/Resources/Assets/user.css b/ReferenceClientProxyImplementation/Resources/Assets/user.css
new file mode 100644
index 0000000..a7e5c4f
--- /dev/null
+++ b/ReferenceClientProxyImplementation/Resources/Assets/user.css
@@ -0,0 +1 @@
+/* Your custom CSS goes here, enjoy! */
\ No newline at end of file
diff --git a/ReferenceClientProxyImplementation/Resources/Assets/widget/banner1.png b/ReferenceClientProxyImplementation/Resources/Assets/widget/banner1.png
new file mode 100644
index 0000000..ed9bd5c
--- /dev/null
+++ b/ReferenceClientProxyImplementation/Resources/Assets/widget/banner1.png
Binary files differdiff --git a/ReferenceClientProxyImplementation/Resources/Assets/widget/banner2.png b/ReferenceClientProxyImplementation/Resources/Assets/widget/banner2.png
new file mode 100644
index 0000000..90d3713
--- /dev/null
+++ b/ReferenceClientProxyImplementation/Resources/Assets/widget/banner2.png
Binary files differdiff --git a/ReferenceClientProxyImplementation/Resources/Assets/widget/banner3.png b/ReferenceClientProxyImplementation/Resources/Assets/widget/banner3.png
new file mode 100644
index 0000000..2235189
--- /dev/null
+++ b/ReferenceClientProxyImplementation/Resources/Assets/widget/banner3.png
Binary files differdiff --git a/ReferenceClientProxyImplementation/Resources/Assets/widget/banner4.png b/ReferenceClientProxyImplementation/Resources/Assets/widget/banner4.png
new file mode 100644
index 0000000..e6bd7b6
--- /dev/null
+++ b/ReferenceClientProxyImplementation/Resources/Assets/widget/banner4.png
Binary files differdiff --git a/ReferenceClientProxyImplementation/Resources/Assets/widget/shield.png b/ReferenceClientProxyImplementation/Resources/Assets/widget/shield.png
new file mode 100644
index 0000000..30277db
--- /dev/null
+++ b/ReferenceClientProxyImplementation/Resources/Assets/widget/shield.png
Binary files differdiff --git a/ReferenceClientProxyImplementation/Resources/Pages/developers.html b/ReferenceClientProxyImplementation/Resources/Pages/developers.html
new file mode 100644
index 0000000..9798554
--- /dev/null
+++ b/ReferenceClientProxyImplementation/Resources/Pages/developers.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html class="theme-dark" data-theme="dark">
+ <head>
+ <meta charset="utf-8"/>
+ <meta content="width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=no" name="viewport"/>
+
+ <link href="/assets/532.03aaeef88460fae60534.css" integrity="" rel="stylesheet"/>
+ <link href="/assets/07dca80a102d4149e9736d4b162cff6f.ico" rel="icon"/>
+ <title>Discord Test Client Developer Portal</title>
+ <meta charset="utf-8" data-react-helmet="true"/>
+ </head>
+
+ <body>
+ <div id="app-mount"></div>
+ <script>
+ window.GLOBAL_ENV = {
+ API_VERSION: 9,
+ API_ENDPOINT: "/api",
+ WEBAPP_ENDPOINT: "",
+ CDN_HOST: `${location.hostname}:3003`,
+
+ BRAINTREE_KEY: "production_5st77rrc_49pp2rp4phym7387",
+ STRIPE_KEY: "pk_live_CUQtlpQUF0vufWpnpUmQvcdi",
+ MARKETING_ENDPOINT: "//discord.com",
+ RELEASE_CHANNEL: "stable",
+ ALGOLIA_KEY: "aca0d7082e4e63af5ba5917d5e96bed0"
+ };
+ GLOBAL_ENV.MEDIA_PROXY_ENDPOINT = location.protocol + "//" + GLOBAL_ENV.CDN_HOST;
+ const localStorage = window.localStorage;
+ // TODO: remote auth
+ // window.GLOBAL_ENV.REMOTE_AUTH_ENDPOINT = window.GLOBAL_ENV.GATEWAY_ENDPOINT.replace(/wss?:/, "");
+ localStorage.setItem("gatewayURL", window.GLOBAL_ENV.GATEWAY_ENDPOINT);
+ localStorage.setItem(
+ "DeveloperOptionsStore",
+ JSON.stringify({
+ trace: false,
+ canary: true,
+ logGatewayEvents: true,
+ logOverlayEvents: true,
+ logAnalyticsEvents: true,
+ sourceMapsEnabled: false,
+ axeEnabled: true,
+ bugReporterEnabled: true,
+ idleStatusIndicatorEnabled: false
+ })
+ );
+ </script>
+ <script integrity="" src="/assets/41fde19fdf180f3d4315.js"></script>
+ <script integrity="" src="/assets/7b04a3ab10e05dd9054e.js"></script>
+ <script integrity="" src="/assets/d1f811da193e5648048b.js"></script>
+ </body>
+</html>
diff --git a/ReferenceClientProxyImplementation/Resources/Pages/index-template.html b/ReferenceClientProxyImplementation/Resources/Pages/index-template.html
new file mode 100644
index 0000000..ef77e22
--- /dev/null
+++ b/ReferenceClientProxyImplementation/Resources/Pages/index-template.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8"/>
+ <meta content="width=device-width, initial-scale=1.0" name="viewport"/>
+ <title>Discord Test Client</title>
+ <link href="/assets/fosscord.css" rel="stylesheet"/>
+ <link href="/assets/fosscord-login.css" id="logincss" rel="stylesheet"/>
+ <link href="/assets/user.css" id="customcss" rel="stylesheet"/>
+ <!-- preload plugin marker -->
+ </head>
+
+ <body>
+ <div id="app-mount"></div>
+ <script>
+ window.__OVERLAY__ = /overlay/.test(location.pathname);
+ window.__BILLING_STANDALONE__ = /^\/billing/.test(location.pathname);
+
+ var xmlhttp = new XMLHttpRequest();
+ var url = "/api/_fosscord/v1/global_env";
+ xmlhttp.onreadystatechange = function () {
+ if (this.readyState == 4 && this.status == 200) {
+ window.GLOBAL_ENV = JSON.parse(this.responseText);
+ }
+ }
+
+ xmlhttp.open("GET", url, false);
+ xmlhttp.send();
+
+
+ const localStorage = window.localStorage;
+ // TODO: remote auth
+ // window.GLOBAL_ENV.REMOTE_AUTH_ENDPOINT = window.GLOBAL_ENV.GATEWAY_ENDPOINT.replace(/wss?:/, "");
+ localStorage.setItem("gatewayURL", window.GLOBAL_ENV.GATEWAY_ENDPOINT);
+ localStorage.setItem(
+ "DeveloperOptionsStore",
+ JSON.stringify({
+ trace: false,
+ canary: true,
+ logGatewayEvents: true,
+ logOverlayEvents: true,
+ logAnalyticsEvents: true,
+ sourceMapsEnabled: false,
+ axeEnabled: true,
+ bugReporterEnabled: true,
+ idleStatusIndicatorEnabled: false
+ })
+ );
+
+ setInterval(() => {
+ var token = JSON.parse(localStorage.getItem("token"));
+ if (token) {
+ var logincss = document.querySelector('#logincss'),
+ canRemove = logincss ? logincss : "";
+ if (canRemove !== "") {
+ document.querySelector("#logincss").remove();
+ canRemove = "";
+ }
+ }
+ }, 1000)
+
+ const settings = JSON.parse(localStorage.getItem("UserSettingsStore"));
+ if (settings && settings.locale.length <= 2) {
+ // fix client locale wrong and client not loading at all
+ settings.locale = "en-US";
+ localStorage.setItem("UserSettingsStore", JSON.stringify(settings));
+ }
+ </script>
+ <!--prefetch_script-->
+ <!--client_css-->
+ <script src="/assets/checkLocale.js"></script>
+ <!--client_script-->
+ <!-- plugin marker -->
+ </body>
+</html>
diff --git a/ReferenceClientProxyImplementation/Resources/Pages/index.html b/ReferenceClientProxyImplementation/Resources/Pages/index.html
new file mode 100644
index 0000000..0b52736
--- /dev/null
+++ b/ReferenceClientProxyImplementation/Resources/Pages/index.html
@@ -0,0 +1,130 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8"/>
+ <meta content="width=device-width, initial-scale=1.0" name="viewport"/>
+ <title>Discord Test Client</title>
+ <link href="/assets/fosscord.css" rel="stylesheet"/>
+ <link href="/assets/fosscord-login.css" id="logincss" rel="stylesheet"/>
+ <link href="/assets/user.css" id="customcss" rel="stylesheet"/>
+ <!-- preload plugin marker -->
+ </head>
+
+ <body>
+ <div id="app-mount"></div>
+ <script>
+ window.__OVERLAY__ = /overlay/.test(location.pathname);
+ window.__BILLING_STANDALONE__ = /^\/billing/.test(location.pathname);
+ window.GLOBAL_ENV = {
+ API_ENDPOINT: "/api",
+ API_VERSION: 9,
+ GATEWAY_ENDPOINT: `${location.protocol === "https:" ? "wss://" : "ws://"}${location.hostname}:2001`,
+ WEBAPP_ENDPOINT: "",
+ CDN_HOST: `${location.hostname}:3003`,
+ ASSET_ENDPOINT: "",
+ MEDIA_PROXY_ENDPOINT: "https://media.discordapp.net",
+ WIDGET_ENDPOINT: `//${location.host}/widget`,
+ INVITE_HOST: `${location.host}/invite`,
+ GUILD_TEMPLATE_HOST: "discord.new",
+ GIFT_CODE_HOST: "discord.gift",
+ RELEASE_CHANNEL: "staging",
+ MARKETING_ENDPOINT: "//discord.com",
+ BRAINTREE_KEY: "production_5st77rrc_49pp2rp4phym7387",
+ STRIPE_KEY: "pk_live_CUQtlpQUF0vufWpnpUmQvcdi",
+ NETWORKING_ENDPOINT: "//router.discordapp.net",
+ RTC_LATENCY_ENDPOINT: "//latency.discord.media/rtc",
+ ACTIVITY_APPLICATION_HOST: 'discordsays.com',
+ PROJECT_ENV: "staging",
+ REMOTE_AUTH_ENDPOINT: "//localhost:3020",
+ SENTRY_TAGS: {buildId: "75e36d9", buildType: "normal"},
+ MIGRATION_SOURCE_ORIGIN: "https://discordapp.com",
+ MIGRATION_DESTINATION_ORIGIN: "https://discord.com",
+ HTML_TIMESTAMP: Date.now(),
+ ALGOLIA_KEY: "aca0d7082e4e63af5ba5917d5e96bed0"
+ };
+ GLOBAL_ENV.MEDIA_PROXY_ENDPOINT = location.protocol + "//" + GLOBAL_ENV.CDN_HOST;
+ const localStorage = window.localStorage;
+ // TODO: remote auth
+ // window.GLOBAL_ENV.REMOTE_AUTH_ENDPOINT = window.GLOBAL_ENV.GATEWAY_ENDPOINT.replace(/wss?:/, "");
+ localStorage.setItem("gatewayURL", window.GLOBAL_ENV.GATEWAY_ENDPOINT);
+ localStorage.setItem(
+ "DeveloperOptionsStore",
+ JSON.stringify({
+ trace: false,
+ canary: true,
+ logGatewayEvents: true,
+ logOverlayEvents: true,
+ logAnalyticsEvents: true,
+ sourceMapsEnabled: false,
+ axeEnabled: true,
+ bugReporterEnabled: true,
+ idleStatusIndicatorEnabled: false
+ })
+ );
+
+ setInterval(() => {
+ var token = JSON.parse(localStorage.getItem("token"));
+ if (token) {
+ var logincss = document.querySelector('#logincss'),
+ canRemove = logincss ? logincss : "";
+ if (canRemove !== "") {
+ document.querySelector("#logincss").remove();
+ canRemove = "";
+ }
+ }
+ }, 1000)
+
+ const settings = JSON.parse(localStorage.getItem("UserSettingsStore"));
+ if (settings && settings.locale.length <= 2) {
+ // fix client locale wrong and client not loading at all
+ settings.locale = "en-US";
+ localStorage.setItem("UserSettingsStore", JSON.stringify(settings));
+ }
+ </script>
+ <link as="script" href="/assets/d110af2d26131beb5874.js" rel="prefetch">
+ <link as="script" href="/assets/b4499d2a6b9046b1b402.js" rel="prefetch">
+ <link as="script" href="/assets/4b58fa778cc38e586a72.js" rel="prefetch">
+ <link as="script" href="/assets/2e45b6b321248222f12a.js" rel="prefetch">
+ <link as="script" href="/assets/2a6b8d1c4c54837fbc1c.js" rel="prefetch">
+ <link as="script" href="/assets/32a385a6252512863141.js" rel="prefetch">
+ <link as="script" href="/assets/66fb582b4c0e8351bd05.js" rel="prefetch">
+ <link as="script" href="/assets/d5b25e619c7d3c54072a.js" rel="prefetch">
+ <link as="script" href="/assets/e03405baa0373b35d236.js" rel="prefetch">
+ <link as="script" href="/assets/7ac1c95d059085cc0b95.js" rel="prefetch">
+ <link as="script" href="/assets/0778eb7c5d969638777f.js" rel="prefetch">
+ <link as="script" href="/assets/d2888bff1a9b35045d7a.js" rel="prefetch">
+ <link as="script" href="/assets/46f8b7fcfcafca99414f.js" rel="prefetch">
+ <link as="script" href="/assets/e2d458306e3a43a03786.js" rel="prefetch">
+ <link as="script" href="/assets/2f6fc578446032c0c0a5.js" rel="prefetch">
+ <link as="script" href="/assets/14a17120248ea20823d1.js" rel="prefetch">
+ <link as="script" href="/assets/0cfed40d2532db2e560f.js" rel="prefetch">
+ <link as="script" href="/assets/f66efd328f8ca3ad6f1d.js" rel="prefetch">
+ <link as="script" href="/assets/a1ad32825016ef835b51.js" rel="prefetch">
+ <link as="script" href="/assets/916a3fd42b56f5b5b0ff.js" rel="prefetch">
+ <link as="script" href="/assets/e4c9aec8e2ccf49c6a43.js" rel="prefetch">
+ <link as="script" href="/assets/4eb8ce79510c19e425f0.js" rel="prefetch">
+ <link as="script" href="/assets/669ce420727060b05505.js" rel="prefetch">
+ <link as="script" href="/assets/90adae2a1e530ee2388a.js" rel="prefetch">
+ <link as="script" href="/assets/95785439b23503f2a4bc.js" rel="prefetch">
+ <link as="script" href="/assets/4dcc4abc98689f0e601b.js" rel="prefetch">
+ <link as="script" href="/assets/50b1f37a5e2c8602463a.js" rel="prefetch">
+ <link as="script" href="/assets/0d7b3701d6136866c7ec.js" rel="prefetch">
+ <link as="script" href="/assets/d84f21f10b08966b8903.js" rel="prefetch">
+ <link as="script" href="/assets/60385fdbdf9f90d8c4c7.js" rel="prefetch">
+ <link as="script" href="/assets/7f327522a62dfbc3fa17.js" rel="prefetch">
+ <link as="script" href="/assets/50ef6fe50ba0096918d9.js" rel="prefetch">
+ <link as="script" href="/assets/6f81e4e1883133e82730.js" rel="prefetch">
+ <link as="script" href="/assets/ec34e6ac622f2adf141a.js" rel="prefetch">
+ <link as="script" href="/assets/1839152a11550e6304c2.js" rel="prefetch">
+ <link as="script" href="/assets/e7ab6471de10e3f701e6.js" rel="prefetch">
+ <link as="script" href="/assets/efb278e1216055e3d1a8.js" rel="prefetch">
+ <link as="script" href="/assets/70093dfc536e766dbb27.js" rel="prefetch">
+ <link href="/assets/40532.bd1a2e262154456bad22.css" rel="stylesheet">
+ <script src="/assets/checkLocale.js"></script>
+ <script src="/assets/81d16d948535e8d77831.js"></script>
+ <script src="/assets/d110af2d26131beb5874.js"></script>
+ <script src="/assets/c44d54de4c931fca740e.js"></script>
+ <script src="/assets/2cc7dd42639b0c3ae762.js"></script>
+ <!-- plugin marker -->
+ </body>
+</html>
diff --git a/ReferenceClientProxyImplementation/Resources/Private/Injections/WebSocketDataLog.html b/ReferenceClientProxyImplementation/Resources/Private/Injections/WebSocketDataLog.html
new file mode 100644
index 0000000..ef16e72
--- /dev/null
+++ b/ReferenceClientProxyImplementation/Resources/Private/Injections/WebSocketDataLog.html
@@ -0,0 +1,7 @@
+<script>
+ window.toHexString = function (byteArray) {
+ return byteArray.reduce((output, elem) =>
+ (output + (elem.toString(16).padStart(2, '0').toUpperCase() + ' ')),
+ '');
+ }
+</script>
\ No newline at end of file
diff --git a/ReferenceClientProxyImplementation/Resources/Private/Injections/WebSocketDumper.html b/ReferenceClientProxyImplementation/Resources/Private/Injections/WebSocketDumper.html
new file mode 100644
index 0000000..14dc989
--- /dev/null
+++ b/ReferenceClientProxyImplementation/Resources/Private/Injections/WebSocketDumper.html
@@ -0,0 +1,22 @@
+<script>
+ window.sockets = [];
+ var lastBuff = '';
+ const nativeWebSocket = window.WebSocket;
+ window.WebSocket = function (...args) {
+ console.log("Starting new websocket");
+ const socket = new nativeWebSocket(...args);
+ window.sockets.push(socket);
+ if (!args[0].includes('spotify'))
+ socket.addEventListener("message", ev => {
+ console.log("Dumping message...");
+ lastBuff = ev.data;
+ var dat = new Uint8Array(lastBuff);
+ if (window.toHexString) console.log(window.toHexString(dat));
+ var xhr = new XMLHttpRequest;
+ xhr.open("POST", "http://localhost:2001/dump/cs", false);
+ xhr.send(ev.data);
+ });
+ console.log("Websocket hooked!", socket);
+ return socket;
+ };
+</script>
\ No newline at end of file
|