diff --git a/assets/client_test/developers.html b/assets/client_test/developers.html
new file mode 100644
index 0000000..59b3b12
--- /dev/null
+++ b/assets/client_test/developers.html
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+ Fosscord Test Client Developer Portal
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/client_test/index.html b/assets/client_test/index.html
new file mode 100644
index 0000000..a2e4039
--- /dev/null
+++ b/assets/client_test/index.html
@@ -0,0 +1,138 @@
+
+
+
+
+
+
+ Fosscord Test Client
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/client_test/public/1f0bfc0865d324c2587920a7d80c609b.png b/assets/client_test/public/1f0bfc0865d324c2587920a7d80c609b.png
new file mode 100644
index 0000000..9b92bd2
--- /dev/null
+++ b/assets/client_test/public/1f0bfc0865d324c2587920a7d80c609b.png
Binary files differ
diff --git a/assets/client_test/public/3c6ccb83716d1e4fb91d3082f6b21d77.png b/assets/client_test/public/3c6ccb83716d1e4fb91d3082f6b21d77.png
new file mode 100644
index 0000000..62c599a
--- /dev/null
+++ b/assets/client_test/public/3c6ccb83716d1e4fb91d3082f6b21d77.png
Binary files differ
diff --git a/assets/client_test/public/4c1b599b1ef5b9f1874fdb9933f3e03b.png b/assets/client_test/public/4c1b599b1ef5b9f1874fdb9933f3e03b.png
new file mode 100644
index 0000000..bd7afef
--- /dev/null
+++ b/assets/client_test/public/4c1b599b1ef5b9f1874fdb9933f3e03b.png
Binary files differ
diff --git a/assets/client_test/public/6f26ddd1bf59740c536d2274bb834a05.png b/assets/client_test/public/6f26ddd1bf59740c536d2274bb834a05.png
new file mode 100644
index 0000000..9f13790
--- /dev/null
+++ b/assets/client_test/public/6f26ddd1bf59740c536d2274bb834a05.png
Binary files differ
diff --git a/assets/client_test/public/7c8f476123d28d103efe381543274c25.png b/assets/client_test/public/7c8f476123d28d103efe381543274c25.png
new file mode 100644
index 0000000..3e8eeae
--- /dev/null
+++ b/assets/client_test/public/7c8f476123d28d103efe381543274c25.png
Binary files differ
diff --git a/assets/client_test/public/c09a43a372ba81e3018c3151d4ed4773.png b/assets/client_test/public/c09a43a372ba81e3018c3151d4ed4773.png
new file mode 100644
index 0000000..67ee7bb
--- /dev/null
+++ b/assets/client_test/public/c09a43a372ba81e3018c3151d4ed4773.png
Binary files differ
diff --git a/assets/client_test/public/endpoints.json b/assets/client_test/public/endpoints.json
new file mode 100644
index 0000000..8b0514c
--- /dev/null
+++ b/assets/client_test/public/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/assets/client_test/public/features.json b/assets/client_test/public/features.json
new file mode 100644
index 0000000..05a858a
--- /dev/null
+++ b/assets/client_test/public/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/assets/client_test/public/fosscord-login.css b/assets/client_test/public/fosscord-login.css
new file mode 100644
index 0000000..76cf806
--- /dev/null
+++ b/assets/client_test/public/fosscord-login.css
@@ -0,0 +1,68 @@
+/* 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;
+}
\ No newline at end of file
diff --git a/assets/client_test/public/fosscord.css b/assets/client_test/public/fosscord.css
new file mode 100644
index 0000000..2ee7b79
--- /dev/null
+++ b/assets/client_test/public/fosscord.css
@@ -0,0 +1,92 @@
+/* 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;
+}
\ No newline at end of file
diff --git a/assets/client_test/public/user.css b/assets/client_test/public/user.css
new file mode 100644
index 0000000..a7e5c4f
--- /dev/null
+++ b/assets/client_test/public/user.css
@@ -0,0 +1 @@
+/* Your custom CSS goes here, enjoy! */
\ No newline at end of file
diff --git a/assets/client_test/verify.html b/assets/client_test/verify.html
new file mode 100644
index 0000000..0de6fc6
--- /dev/null
+++ b/assets/client_test/verify.html
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+ Fosscord Test Client
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/assets/inline-plugins/.gitkeep b/assets/inline-plugins/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/assets/inline-plugins/.gitkeep
diff --git a/assets/openapi.json b/assets/openapi.json
index b544528..26c330a 100644
--- a/assets/openapi.json
+++ b/assets/openapi.json
@@ -3767,9 +3767,7 @@
"additionalProperties": false
},
"intents": {
- "type": "number",
- "properties": {},
- "additionalProperties": false
+ "type": "number"
},
"presence": {
"$ref": "#/components/schemas/ActivitySchema"
@@ -3788,9 +3786,7 @@
"maxItems": 2,
"type": "array",
"items": {
- "type": "number",
- "properties": {},
- "additionalProperties": false
+ "type": "number"
}
},
"guild_subscriptions": {
@@ -10872,6 +10868,9 @@
"$ref": "#/components/schemas/MessageSnapshot"
}
},
+ "isWebhook": {
+ "type": "boolean"
+ },
"id": {
"type": "string"
}
@@ -10881,6 +10880,7 @@
"embeds",
"flags",
"id",
+ "isWebhook",
"mention_channels",
"mention_roles",
"mentions",
diff --git a/assets/plugins/.gitkeep b/assets/plugins/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/assets/plugins/.gitkeep
diff --git a/assets/preload-plugins/.gitkeep b/assets/preload-plugins/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/assets/preload-plugins/.gitkeep
diff --git a/assets/preload-plugins/checkLocale.js b/assets/preload-plugins/checkLocale.js
new file mode 100644
index 0000000..1b5e7b7
--- /dev/null
+++ b/assets/preload-plugins/checkLocale.js
@@ -0,0 +1,38 @@
+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(window.localStorage.getItem("UserSettingsStore"));
+if (settings && !supportedLocales.includes(settings.locale)) {
+ // fix client locale wrong and client not loading at all
+ settings.locale = "en-US";
+ window.localStorage.setItem("UserSettingsStore", JSON.stringify(settings));
+}
\ No newline at end of file
diff --git a/assets/preload-plugins/oauth2.js b/assets/preload-plugins/oauth2.js
new file mode 100644
index 0000000..5b78ec8
--- /dev/null
+++ b/assets/preload-plugins/oauth2.js
@@ -0,0 +1,9 @@
+// Fixes /oauth2 endpoints not requesting a CSS file
+
+if (location.pathname.startsWith("/oauth2/")) {
+ const link = document.createElement("link");
+ link.rel = "stylesheet"
+ link.type = "text/css"
+ link.href = "/assets/40532.f7b1e10347ef10e790ac.css"
+ document.head.appendChild(link)
+}
\ No newline at end of file
diff --git a/assets/public/1276374a404452756f3c9cc2601508a5.png b/assets/public/1276374a404452756f3c9cc2601508a5.png
deleted file mode 100644
index b9f7f62..0000000
--- a/assets/public/1276374a404452756f3c9cc2601508a5.png
+++ /dev/null
Binary files differ
diff --git a/assets/public/1f0bfc0865d324c2587920a7d80c609b.png b/assets/public/1f0bfc0865d324c2587920a7d80c609b.png
new file mode 100644
index 0000000..9b92bd2
--- /dev/null
+++ b/assets/public/1f0bfc0865d324c2587920a7d80c609b.png
Binary files differ
diff --git a/assets/public/22341bdb500c7b63a93bbce957d1601e.png b/assets/public/22341bdb500c7b63a93bbce957d1601e.png
deleted file mode 100644
index c8bf93d..0000000
--- a/assets/public/22341bdb500c7b63a93bbce957d1601e.png
+++ /dev/null
Binary files differ
diff --git a/assets/public/2e46fe14586f8e95471c0917f56726b5.png b/assets/public/2e46fe14586f8e95471c0917f56726b5.png
deleted file mode 100644
index bf747d7..0000000
--- a/assets/public/2e46fe14586f8e95471c0917f56726b5.png
+++ /dev/null
Binary files differ
diff --git a/assets/public/3b70bb66089c60f8be5e214bf8574c9d.png b/assets/public/3b70bb66089c60f8be5e214bf8574c9d.png
deleted file mode 100644
index c4f95d9..0000000
--- a/assets/public/3b70bb66089c60f8be5e214bf8574c9d.png
+++ /dev/null
Binary files differ
diff --git a/assets/public/3c6ccb83716d1e4fb91d3082f6b21d77.png b/assets/public/3c6ccb83716d1e4fb91d3082f6b21d77.png
new file mode 100644
index 0000000..62c599a
--- /dev/null
+++ b/assets/public/3c6ccb83716d1e4fb91d3082f6b21d77.png
Binary files differ
diff --git a/assets/public/4a8562cf00887030c416d3ec2d46385a.png b/assets/public/4a8562cf00887030c416d3ec2d46385a.png
deleted file mode 100644
index 73426bc..0000000
--- a/assets/public/4a8562cf00887030c416d3ec2d46385a.png
+++ /dev/null
Binary files differ
diff --git a/assets/public/4ab900144b0865430dc9be825c838faa.png b/assets/public/4ab900144b0865430dc9be825c838faa.png
deleted file mode 100644
index f3ba032..0000000
--- a/assets/public/4ab900144b0865430dc9be825c838faa.png
+++ /dev/null
Binary files differ
diff --git a/assets/public/4c1b599b1ef5b9f1874fdb9933f3e03b.png b/assets/public/4c1b599b1ef5b9f1874fdb9933f3e03b.png
new file mode 100644
index 0000000..bd7afef
--- /dev/null
+++ b/assets/public/4c1b599b1ef5b9f1874fdb9933f3e03b.png
Binary files differ
diff --git a/assets/public/6f26ddd1bf59740c536d2274bb834a05.png b/assets/public/6f26ddd1bf59740c536d2274bb834a05.png
new file mode 100644
index 0000000..9f13790
--- /dev/null
+++ b/assets/public/6f26ddd1bf59740c536d2274bb834a05.png
Binary files differ
diff --git a/assets/public/7213ab6677377974697dfdfbaf5f6a6f.png b/assets/public/7213ab6677377974697dfdfbaf5f6a6f.png
deleted file mode 100644
index f1fa9f0..0000000
--- a/assets/public/7213ab6677377974697dfdfbaf5f6a6f.png
+++ /dev/null
Binary files differ
diff --git a/assets/public/7c8f476123d28d103efe381543274c25.png b/assets/public/7c8f476123d28d103efe381543274c25.png
new file mode 100644
index 0000000..3e8eeae
--- /dev/null
+++ b/assets/public/7c8f476123d28d103efe381543274c25.png
Binary files differ
diff --git a/assets/public/904bf9f1b61f53ef4a3b7a893afeabe3.png b/assets/public/904bf9f1b61f53ef4a3b7a893afeabe3.png
deleted file mode 100644
index 0cac967..0000000
--- a/assets/public/904bf9f1b61f53ef4a3b7a893afeabe3.png
+++ /dev/null
Binary files differ
diff --git a/assets/public/9581acd31832465bdeaa5385b0e919a3.png b/assets/public/9581acd31832465bdeaa5385b0e919a3.png
deleted file mode 100644
index 1026155..0000000
--- a/assets/public/9581acd31832465bdeaa5385b0e919a3.png
+++ /dev/null
Binary files differ
diff --git a/assets/public/9b0bb198936784c45c72833cc426cc55.png b/assets/public/9b0bb198936784c45c72833cc426cc55.png
deleted file mode 100644
index 367051c..0000000
--- a/assets/public/9b0bb198936784c45c72833cc426cc55.png
+++ /dev/null
Binary files differ
diff --git a/assets/public/9d6ddb4e4d899a533a8cc617011351c9.png b/assets/public/9d6ddb4e4d899a533a8cc617011351c9.png
deleted file mode 100644
index 740cdd2..0000000
--- a/assets/public/9d6ddb4e4d899a533a8cc617011351c9.png
+++ /dev/null
Binary files differ
diff --git a/assets/public/a8a4727cf2dc2939bd3c657fad4463fa.png b/assets/public/a8a4727cf2dc2939bd3c657fad4463fa.png
deleted file mode 100644
index 35f16cc..0000000
--- a/assets/public/a8a4727cf2dc2939bd3c657fad4463fa.png
+++ /dev/null
Binary files differ
diff --git a/assets/public/c09a43a372ba81e3018c3151d4ed4773.png b/assets/public/c09a43a372ba81e3018c3151d4ed4773.png
new file mode 100644
index 0000000..67ee7bb
--- /dev/null
+++ b/assets/public/c09a43a372ba81e3018c3151d4ed4773.png
Binary files differ
diff --git a/assets/public/d9977836b82058bf2f74eebd50edc095.png b/assets/public/d9977836b82058bf2f74eebd50edc095.png
deleted file mode 100644
index bb73cd9..0000000
--- a/assets/public/d9977836b82058bf2f74eebd50edc095.png
+++ /dev/null
Binary files differ
diff --git a/assets/public/fac7e78de9753d4a37083bba74c1d9ef.png b/assets/public/fac7e78de9753d4a37083bba74c1d9ef.png
deleted file mode 100644
index 78b66c7..0000000
--- a/assets/public/fac7e78de9753d4a37083bba74c1d9ef.png
+++ /dev/null
Binary files differ
diff --git a/assets/public/fosscord-login.css b/assets/public/fosscord-login.css
new file mode 100644
index 0000000..76cf806
--- /dev/null
+++ b/assets/public/fosscord-login.css
@@ -0,0 +1,68 @@
+/* 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;
+}
\ No newline at end of file
diff --git a/assets/public/fosscord.css b/assets/public/fosscord.css
new file mode 100644
index 0000000..2ee7b79
--- /dev/null
+++ b/assets/public/fosscord.css
@@ -0,0 +1,92 @@
+/* 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;
+}
\ No newline at end of file
diff --git a/assets/public/index.html b/assets/public/index.html
deleted file mode 100644
index 3723cab..0000000
--- a/assets/public/index.html
+++ /dev/null
@@ -1,65 +0,0 @@
-
-
-
-
-
-
-
- Spacebar Server
-
-
-
-
-
-
-
-
-
-
-

-
-
Welcome!
-
If you're viewing this page, that means you've successfully set up your very own Spacebar instance!
-
For information on how to configure your shiny new setup, you should visit our documentation
-
For information on how to connect and use your instance, click here
-
-
-
-
\ No newline at end of file
diff --git a/assets/public/user.css b/assets/public/user.css
new file mode 100644
index 0000000..a7e5c4f
--- /dev/null
+++ b/assets/public/user.css
@@ -0,0 +1 @@
+/* Your custom CSS goes here, enjoy! */
\ No newline at end of file
diff --git a/assets/public/verify.html b/assets/public/verify.html
deleted file mode 100644
index 83ce865..0000000
--- a/assets/public/verify.html
+++ /dev/null
@@ -1,292 +0,0 @@
-
-
-
-
-
-
- Spacebar Server
-
-
-
-
-
-
-
-
-
-
-

-
-
-
Verifying your email
-
Please wait...
-
-
-
-
-
-
diff --git a/assets/public/widget.html b/assets/public/widget.html
deleted file mode 100644
index b72e1d9..0000000
--- a/assets/public/widget.html
+++ /dev/null
@@ -1,175 +0,0 @@
-
-
-
-
-
-
-
- Spacebar Widget
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/assets/publicold/1276374a404452756f3c9cc2601508a5.png b/assets/publicold/1276374a404452756f3c9cc2601508a5.png
new file mode 100644
index 0000000..b9f7f62
--- /dev/null
+++ b/assets/publicold/1276374a404452756f3c9cc2601508a5.png
Binary files differ
diff --git a/assets/publicold/22341bdb500c7b63a93bbce957d1601e.png b/assets/publicold/22341bdb500c7b63a93bbce957d1601e.png
new file mode 100644
index 0000000..c8bf93d
--- /dev/null
+++ b/assets/publicold/22341bdb500c7b63a93bbce957d1601e.png
Binary files differ
diff --git a/assets/publicold/2e46fe14586f8e95471c0917f56726b5.png b/assets/publicold/2e46fe14586f8e95471c0917f56726b5.png
new file mode 100644
index 0000000..bf747d7
--- /dev/null
+++ b/assets/publicold/2e46fe14586f8e95471c0917f56726b5.png
Binary files differ
diff --git a/assets/publicold/3b70bb66089c60f8be5e214bf8574c9d.png b/assets/publicold/3b70bb66089c60f8be5e214bf8574c9d.png
new file mode 100644
index 0000000..c4f95d9
--- /dev/null
+++ b/assets/publicold/3b70bb66089c60f8be5e214bf8574c9d.png
Binary files differ
diff --git a/assets/publicold/4a8562cf00887030c416d3ec2d46385a.png b/assets/publicold/4a8562cf00887030c416d3ec2d46385a.png
new file mode 100644
index 0000000..73426bc
--- /dev/null
+++ b/assets/publicold/4a8562cf00887030c416d3ec2d46385a.png
Binary files differ
diff --git a/assets/publicold/4ab900144b0865430dc9be825c838faa.png b/assets/publicold/4ab900144b0865430dc9be825c838faa.png
new file mode 100644
index 0000000..f3ba032
--- /dev/null
+++ b/assets/publicold/4ab900144b0865430dc9be825c838faa.png
Binary files differ
diff --git a/assets/publicold/7213ab6677377974697dfdfbaf5f6a6f.png b/assets/publicold/7213ab6677377974697dfdfbaf5f6a6f.png
new file mode 100644
index 0000000..f1fa9f0
--- /dev/null
+++ b/assets/publicold/7213ab6677377974697dfdfbaf5f6a6f.png
Binary files differ
diff --git a/assets/publicold/904bf9f1b61f53ef4a3b7a893afeabe3.png b/assets/publicold/904bf9f1b61f53ef4a3b7a893afeabe3.png
new file mode 100644
index 0000000..0cac967
--- /dev/null
+++ b/assets/publicold/904bf9f1b61f53ef4a3b7a893afeabe3.png
Binary files differ
diff --git a/assets/publicold/9581acd31832465bdeaa5385b0e919a3.png b/assets/publicold/9581acd31832465bdeaa5385b0e919a3.png
new file mode 100644
index 0000000..1026155
--- /dev/null
+++ b/assets/publicold/9581acd31832465bdeaa5385b0e919a3.png
Binary files differ
diff --git a/assets/publicold/9b0bb198936784c45c72833cc426cc55.png b/assets/publicold/9b0bb198936784c45c72833cc426cc55.png
new file mode 100644
index 0000000..367051c
--- /dev/null
+++ b/assets/publicold/9b0bb198936784c45c72833cc426cc55.png
Binary files differ
diff --git a/assets/publicold/9d6ddb4e4d899a533a8cc617011351c9.png b/assets/publicold/9d6ddb4e4d899a533a8cc617011351c9.png
new file mode 100644
index 0000000..740cdd2
--- /dev/null
+++ b/assets/publicold/9d6ddb4e4d899a533a8cc617011351c9.png
Binary files differ
diff --git a/assets/publicold/a8a4727cf2dc2939bd3c657fad4463fa.png b/assets/publicold/a8a4727cf2dc2939bd3c657fad4463fa.png
new file mode 100644
index 0000000..35f16cc
--- /dev/null
+++ b/assets/publicold/a8a4727cf2dc2939bd3c657fad4463fa.png
Binary files differ
diff --git a/assets/publicold/d9977836b82058bf2f74eebd50edc095.png b/assets/publicold/d9977836b82058bf2f74eebd50edc095.png
new file mode 100644
index 0000000..bb73cd9
--- /dev/null
+++ b/assets/publicold/d9977836b82058bf2f74eebd50edc095.png
Binary files differ
diff --git a/assets/publicold/endpoints.json b/assets/publicold/endpoints.json
new file mode 100644
index 0000000..8b0514c
--- /dev/null
+++ b/assets/publicold/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/assets/publicold/fac7e78de9753d4a37083bba74c1d9ef.png b/assets/publicold/fac7e78de9753d4a37083bba74c1d9ef.png
new file mode 100644
index 0000000..78b66c7
--- /dev/null
+++ b/assets/publicold/fac7e78de9753d4a37083bba74c1d9ef.png
Binary files differ
diff --git a/assets/publicold/features.json b/assets/publicold/features.json
new file mode 100644
index 0000000..05a858a
--- /dev/null
+++ b/assets/publicold/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/assets/publicold/index.html b/assets/publicold/index.html
new file mode 100644
index 0000000..3723cab
--- /dev/null
+++ b/assets/publicold/index.html
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+ Spacebar Server
+
+
+
+
+
+
+
+
+
+
+

+
+
Welcome!
+
If you're viewing this page, that means you've successfully set up your very own Spacebar instance!
+
For information on how to configure your shiny new setup, you should visit our documentation
+
For information on how to connect and use your instance, click here
+
+
+
+
\ No newline at end of file
diff --git a/assets/publicold/verify.html b/assets/publicold/verify.html
new file mode 100644
index 0000000..83ce865
--- /dev/null
+++ b/assets/publicold/verify.html
@@ -0,0 +1,292 @@
+
+
+
+
+
+
+ Spacebar Server
+
+
+
+
+
+
+
+
+
+
+

+
+
+
Verifying your email
+
Please wait...
+
+
+
+
+
+
diff --git a/assets/publicold/widget.html b/assets/publicold/widget.html
new file mode 100644
index 0000000..b72e1d9
--- /dev/null
+++ b/assets/publicold/widget.html
@@ -0,0 +1,175 @@
+
+
+
+
+
+
+
+ Spacebar Widget
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/assets/schemas.json b/assets/schemas.json
index 3d4c30c..89841e8 100644
--- a/assets/schemas.json
+++ b/assets/schemas.json
@@ -3993,9 +3993,7 @@
"additionalProperties": false
},
"intents": {
- "type": "number",
- "properties": {},
- "additionalProperties": false
+ "type": "bigint"
},
"presence": {
"$ref": "#/definitions/ActivitySchema"
@@ -4014,9 +4012,7 @@
"maxItems": 2,
"type": "array",
"items": {
- "type": "number",
- "properties": {},
- "additionalProperties": false
+ "type": "bigint"
}
},
"guild_subscriptions": {
@@ -11552,6 +11548,9 @@
"$ref": "#/definitions/MessageSnapshot"
}
},
+ "isWebhook": {
+ "type": "boolean"
+ },
"id": {
"type": "string"
}
@@ -11562,6 +11561,7 @@
"embeds",
"flags",
"id",
+ "isWebhook",
"mention_channels",
"mention_roles",
"mentions",
diff --git a/assets/widget/banner1.png b/assets/widget/banner1.png
new file mode 100644
index 0000000..ed9bd5c
--- /dev/null
+++ b/assets/widget/banner1.png
Binary files differ
diff --git a/assets/widget/banner2.png b/assets/widget/banner2.png
new file mode 100644
index 0000000..90d3713
--- /dev/null
+++ b/assets/widget/banner2.png
Binary files differ
diff --git a/assets/widget/banner3.png b/assets/widget/banner3.png
new file mode 100644
index 0000000..2235189
--- /dev/null
+++ b/assets/widget/banner3.png
Binary files differ
diff --git a/assets/widget/banner4.png b/assets/widget/banner4.png
new file mode 100644
index 0000000..e6bd7b6
--- /dev/null
+++ b/assets/widget/banner4.png
Binary files differ
diff --git a/assets/widget/shield.png b/assets/widget/shield.png
new file mode 100644
index 0000000..30277db
--- /dev/null
+++ b/assets/widget/shield.png
Binary files differ
diff --git a/package-lock.json b/package-lock.json
index 659cd6a..5924712 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -43,11 +43,13 @@
"multer": "^2.1.1",
"murmurhash-js": "^1.0.0",
"node-2fa": "^2.0.3",
+ "node-fetch": "^3.3.2",
"pg": "^8.21.0",
"pg-query-stream": "^4.15.0",
"picocolors": "^1.1.1",
"probe-image-size": "^7.3.0",
"prom-client": "^15.1.3",
+ "proxy-agent": "^8.0.2",
"reflect-metadata": "^0.2.2",
"tslib": "^2.8.1",
"typeorm": "^0.3.30",
@@ -2195,6 +2197,18 @@
"node": ">=12.0.0"
}
},
+ "node_modules/ast-types": {
+ "version": "0.13.4",
+ "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz",
+ "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -2306,6 +2320,15 @@
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"license": "MIT"
},
+ "node_modules/basic-ftp": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.1.tgz",
+ "integrity": "sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
"node_modules/bcrypt": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz",
@@ -2894,6 +2917,15 @@
"url": "https://github.com/sponsors/fb55"
}
},
+ "node_modules/data-uri-to-buffer": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
+ "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
"node_modules/dayjs": {
"version": "1.11.20",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.20.tgz",
@@ -2965,6 +2997,23 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/degenerator": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-7.0.1.tgz",
+ "integrity": "sha512-ABErK0IefDSyHjlPH7WUEenIAX2rPPnrDcDM+TS3z3+zu9TfyKKi07BQM+8rmxpdE2y1v5fjjdoAS/x4D2U60w==",
+ "license": "MIT",
+ "dependencies": {
+ "ast-types": "^0.13.4",
+ "escodegen": "^2.1.0",
+ "esprima": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 20"
+ },
+ "peerDependencies": {
+ "quickjs-wasi": "^2.2.0"
+ }
+ },
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -3254,6 +3303,27 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/escodegen": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
+ "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esprima": "^4.0.1",
+ "estraverse": "^5.2.0",
+ "esutils": "^2.0.2"
+ },
+ "bin": {
+ "escodegen": "bin/escodegen.js",
+ "esgenerate": "bin/esgenerate.js"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "optionalDependencies": {
+ "source-map": "~0.6.1"
+ }
+ },
"node_modules/eslint": {
"version": "9.39.4",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz",
@@ -3474,6 +3544,19 @@
"url": "https://opencollective.com/eslint"
}
},
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "license": "BSD-2-Clause",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/esquery": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
@@ -3504,7 +3587,6 @@
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
- "dev": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">=4.0"
@@ -3514,7 +3596,6 @@
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
- "dev": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">=0.10.0"
@@ -3642,6 +3723,29 @@
"url": "https://patreon.com/timotejroiko"
}
},
+ "node_modules/fetch-blob": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
+ "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/jimmywarting"
+ },
+ {
+ "type": "paypal",
+ "url": "https://paypal.me/jimmywarting"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "node-domexception": "^1.0.0",
+ "web-streams-polyfill": "^3.0.3"
+ },
+ "engines": {
+ "node": "^12.20 || >= 14.13"
+ }
+ },
"node_modules/fido2-lib": {
"version": "3.5.9",
"resolved": "https://registry.npmjs.org/fido2-lib/-/fido2-lib-3.5.9.tgz",
@@ -3863,6 +3967,18 @@
"node": ">= 0.6"
}
},
+ "node_modules/formdata-polyfill": {
+ "version": "4.0.10",
+ "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
+ "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
+ "license": "MIT",
+ "dependencies": {
+ "fetch-blob": "^3.1.2"
+ },
+ "engines": {
+ "node": ">=12.20.0"
+ }
+ },
"node_modules/forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
@@ -3964,6 +4080,29 @@
"node": ">= 0.4"
}
},
+ "node_modules/get-uri": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-8.0.1.tgz",
+ "integrity": "sha512-/5N/P4Lrh0p/mDwlDRi7Y1+P2o/OyzZI3l6Iz1Ov6XXwwm1y3RlZLuo3gVgML99djrEDtV980bBxSuOeHLk8ww==",
+ "license": "MIT",
+ "dependencies": {
+ "basic-ftp": "^5.3.1",
+ "data-uri-to-buffer": "8.0.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/get-uri/node_modules/data-uri-to-buffer": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-8.0.0.tgz",
+ "integrity": "sha512-6UHfyCux51b8PTGDgveqtz1tvphBku5DrMKKJbFAZAJOI2zsjDpDoYE1+QGj7FOMS4BdTFNJsJiR3zEB0xH0yQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 20"
+ }
+ },
"node_modules/gifwrap": {
"version": "0.10.1",
"resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.10.1.tgz",
@@ -4183,6 +4322,29 @@
"url": "https://opencollective.com/express"
}
},
+ "node_modules/http-proxy-agent": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-9.1.0.tgz",
+ "integrity": "sha512-2NxoveTT58mjYT4n3RPTEfCZGLMbidoO8XEieXfpSYxu+PQJ1qpx4ypwH6N+uF9twBPIvRRgvkvW5HUTYWENig==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "9.0.0",
+ "debug": "^4.3.4",
+ "proxy-agent-negotiate": "1.1.0"
+ },
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/http-proxy-agent/node_modules/agent-base": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-9.0.0.tgz",
+ "integrity": "sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 20"
+ }
+ },
"node_modules/https-proxy-agent": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
@@ -4361,6 +4523,15 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"license": "ISC"
},
+ "node_modules/ip-address": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz",
+ "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
"node_modules/ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@@ -5111,6 +5282,15 @@
"node": ">= 0.6"
}
},
+ "node_modules/netmask": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.1.1.tgz",
+ "integrity": "sha512-eonl3sLUha+S1GzTPxychyhnUzKyeQkZ7jLjKrBagJgPla13F+uQ71HgpFefyHgqrjEbCPkDArxYsjY8/+gLKA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
"node_modules/node-2fa": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/node-2fa/-/node-2fa-2.0.3.tgz",
@@ -5132,6 +5312,44 @@
"node": "^18 || ^20 || >= 21"
}
},
+ "node_modules/node-domexception": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
+ "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
+ "deprecated": "Use your platform's native DOMException instead",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/jimmywarting"
+ },
+ {
+ "type": "github",
+ "url": "https://paypal.me/jimmywarting"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.5.0"
+ }
+ },
+ "node_modules/node-fetch": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
+ "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
+ "license": "MIT",
+ "dependencies": {
+ "data-uri-to-buffer": "^4.0.0",
+ "fetch-blob": "^3.1.4",
+ "formdata-polyfill": "^4.0.10"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/node-fetch"
+ }
+ },
"node_modules/node-gyp-build": {
"version": "4.8.4",
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
@@ -5330,6 +5548,64 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/pac-proxy-agent": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-9.1.0.tgz",
+ "integrity": "sha512-1aU+1mpj3DrQPfo3gh+3Gap3G5x+axnMx1P/y0ZF2ch7kb2meyOCAH8K2k9d27ROsTE7TnAerzxqF9aon2jqnA==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "9.0.0",
+ "debug": "^4.3.4",
+ "get-uri": "8.0.1",
+ "http-proxy-agent": "9.1.0",
+ "https-proxy-agent": "9.1.0",
+ "pac-resolver": "9.0.1",
+ "quickjs-wasi": "^2.2.0",
+ "socks-proxy-agent": "10.1.0"
+ },
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/pac-proxy-agent/node_modules/agent-base": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-9.0.0.tgz",
+ "integrity": "sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/pac-proxy-agent/node_modules/https-proxy-agent": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-9.1.0.tgz",
+ "integrity": "sha512-ag87y7cJJ9/3+GxFr8Oy4O5faDsGRGnBGsJj/YjOSsSx/5eadKLYTMPlzuR6obgoCDDm0abAAZitXXQkMOPSpA==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "9.0.0",
+ "debug": "^4.3.4",
+ "proxy-agent-negotiate": "1.1.0"
+ },
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/pac-resolver": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-9.0.1.tgz",
+ "integrity": "sha512-lJbS008tmkj08VhoM8Hzuv/VE5tK9MS0OIQ/7+s0lIF+BYhiQWFYzkSpML7lXs9iBu2jfmzBTLzhe9n6BX+dYw==",
+ "license": "MIT",
+ "dependencies": {
+ "degenerator": "7.0.1",
+ "netmask": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 20"
+ },
+ "peerDependencies": {
+ "quickjs-wasi": "^2.2.0"
+ }
+ },
"node_modules/package-json-from-dist": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
@@ -5918,12 +6194,79 @@
"node": ">= 0.10"
}
},
+ "node_modules/proxy-agent": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-8.0.2.tgz",
+ "integrity": "sha512-idLLRewuemWd7GH/BDJzGiB0dWGfT2SQs3jy6NtZtGWU9uPTTSdeC1/cdbqLwgzhfv027daGFuXX426e2Eg20A==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "9.0.0",
+ "debug": "^4.3.4",
+ "http-proxy-agent": "9.1.0",
+ "https-proxy-agent": "9.1.0",
+ "lru-cache": "^7.14.1",
+ "pac-proxy-agent": "9.1.0",
+ "proxy-from-env": "^2.0.0",
+ "socks-proxy-agent": "10.1.0"
+ },
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/proxy-agent-negotiate": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-agent-negotiate/-/proxy-agent-negotiate-1.1.0.tgz",
+ "integrity": "sha512-N8IBcM3UgCVzz2L2Lqv8DVntDnnC8/hiV4nEDUPkqq72TPUgYWjQc+bdZlBPZK9LzPAvOY//gAt0S0DApoOXWQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 20"
+ },
+ "peerDependencies": {
+ "kerberos": "^2.0.0"
+ },
+ "peerDependenciesMeta": {
+ "kerberos": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/proxy-agent/node_modules/agent-base": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-9.0.0.tgz",
+ "integrity": "sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/proxy-agent/node_modules/https-proxy-agent": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-9.1.0.tgz",
+ "integrity": "sha512-ag87y7cJJ9/3+GxFr8Oy4O5faDsGRGnBGsJj/YjOSsSx/5eadKLYTMPlzuR6obgoCDDm0abAAZitXXQkMOPSpA==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "9.0.0",
+ "debug": "^4.3.4",
+ "proxy-agent-negotiate": "1.1.0"
+ },
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/proxy-agent/node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/proxy-from-env": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
"integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
"license": "MIT",
- "optional": true,
"engines": {
"node": ">=10"
}
@@ -5980,6 +6323,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/quickjs-wasi": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/quickjs-wasi/-/quickjs-wasi-2.2.0.tgz",
+ "integrity": "sha512-zQxXmQMrEoD3S+jQdYsloq4qAuaxKFHZj6hHqOYGwB2iQZH+q9e/lf5zQPXCKOk0WJuAjzRFbO4KwHIp2D05Iw==",
+ "license": "MIT"
+ },
"node_modules/randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@@ -6367,6 +6716,63 @@
"node": ">=6"
}
},
+ "node_modules/smart-buffer": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
+ "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/socks": {
+ "version": "2.8.9",
+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.9.tgz",
+ "integrity": "sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw==",
+ "license": "MIT",
+ "dependencies": {
+ "ip-address": "^10.1.1",
+ "smart-buffer": "^4.2.0"
+ },
+ "engines": {
+ "node": ">= 10.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/socks-proxy-agent": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-10.1.0.tgz",
+ "integrity": "sha512-WlMj/67cEJ6MDI1OcsnjuYKDNDoyPCCYZ249kuuXPiMDw9F8PXkVaQ7YWu3siTydfQ/4BEZcvGzu+aYvz7dDCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "9.0.0",
+ "debug": "^4.3.4",
+ "socks": "^2.8.3"
+ },
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/socks-proxy-agent/node_modules/agent-base": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-9.0.0.tgz",
+ "integrity": "sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/split2": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
@@ -7343,6 +7749,15 @@
"node": ">=6.0"
}
},
+ "node_modules/web-streams-polyfill": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
+ "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
"node_modules/webcrypto-core": {
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.9.2.tgz",
diff --git a/package.json b/package.json
index f20e31d..20149ea 100644
--- a/package.json
+++ b/package.json
@@ -111,11 +111,13 @@
"multer": "^2.1.1",
"murmurhash-js": "^1.0.0",
"node-2fa": "^2.0.3",
+ "node-fetch": "^3.3.2",
"pg": "^8.21.0",
"pg-query-stream": "^4.15.0",
"picocolors": "^1.1.1",
"probe-image-size": "^7.3.0",
"prom-client": "^15.1.3",
+ "proxy-agent": "^8.0.2",
"reflect-metadata": "^0.2.2",
"tslib": "^2.8.1",
"typeorm": "^0.3.30",
diff --git a/src/api/Server.ts b/src/api/Server.ts
index 9e4bb93..3627e71 100644
--- a/src/api/Server.ts
+++ b/src/api/Server.ts
@@ -17,7 +17,7 @@
*/
import path from "node:path";
-import { Request, Response, Router } from "express";
+import express, { Request, Response, Router } from "express";
import morgan from "morgan";
import { Server, ServerOptions } from "lambert-server";
import { red } from "picocolors";
@@ -25,10 +25,14 @@
import { Authentication, CORS, ImageProxy, BodyParser, ErrorHandler, initRateLimits, initTranslation } from "./middlewares";
import { initInstance } from "./util/handlers/Instance";
import { route } from "./util";
+import fs from "node:fs";
import { ProcessLifecycle } from "../util/util/ProcessLifecycle";
import { Monitoring } from "../util/monitoring/Monitoring";
import { BcryptWorkerPool } from "../util/util/workers/bcrypt/BcryptWorkerPool";
+import { applyEnv, applyPlugins } from "./middlewares/TestClient";
+import fetch, { Response as FetchResponse, Headers } from "node-fetch";
+const ASSET_FOLDER_PATH = path.join(__dirname, "..", "..", "assets");
const ASSETS_FOLDER = path.join(__dirname, "..", "..", "assets");
const PUBLIC_ASSETS_FOLDER = path.join(ASSETS_FOLDER, "public");
@@ -87,7 +91,8 @@
this.app.use(BodyParser({ inflate: true, limit: "10mb" }));
const app = this.app;
- const api = Router({ mergeParams: true });
+ //const api = Router({ mergeParams: true });
+ const api = Router();
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
this.app = api;
@@ -98,17 +103,22 @@
this.routes = (await registerRoutes(this, path.join(__dirname, "routes", "/"))).filter((r) => !!r);
+ api.use((req, res, next) => {
+ console.log(`[Server API Router] Incoming request: ${req.method} ${req.url}`);
+ next();
+ });
+
// 404 is not an error in express, so this should not be an error middleware
// this is a fine place to put the 404 handler because its after we register the routes
// and since its not an error middleware, our error handler below still works.
// Emma [it/its] @ Rory& - the _ is required now, as pillarjs throw an error if you don't pass a param name now
- api.use("*_", (req: Request, res: Response) => {
- res.status(404).json({
- message: "Endpoint not found",
- code: 404,
- request: `${req.method} ${req.url}`,
- });
- });
+ // api.use("*_", (req: Request, res: Response) => {
+ // res.status(404).json({
+ // message: "Endpoint not found",
+ // code: 404,
+ // request: `${req.method} ${req.url}`,
+ // });
+ // });
this.app = app;
@@ -120,14 +130,14 @@
app.use("/api/v8", api);
app.use("/api/v9", api);
app.use("/api/v10", api); // https://discord.com/developers/docs/change-log#api-v10
- app.use("/api", api); // allow unversioned requests
+ // app.use("/api", api); // allow unversioned requests
app.use("/imageproxy/:hash/:size/:url", ImageProxy);
- app.get("/", (req, res) => {
- res.set("Cache-Control", "public, max-age=21600");
- return res.sendFile(path.join(PUBLIC_ASSETS_FOLDER, "index.html"));
- });
+ // app.get("/", (req, res) => {
+ // res.set("Cache-Control", "public, max-age=21600");
+ // return res.sendFile(path.join(PUBLIC_ASSETS_FOLDER, "index.html"));
+ // });
app.get("/verify-email", (req, res) => {
res.set("Cache-Control", "public, max-age=21600");
@@ -154,6 +164,13 @@
});
});
+ let html = fs.readFileSync(path.join(ASSET_FOLDER_PATH, "client_test", "index.html"), { encoding: "utf-8" });
+ console.log("call 3");
+
+ html = applyEnv(html); // update window.GLOBAL_ENV according to config
+
+ html = applyPlugins(html); // inject our plugins
+
// current well-known location
app.get("/.well-known/spacebar", (req, res) => {
res.json({
@@ -202,6 +219,72 @@
if (logRequests) console.log(red(`Warning: Request logging is enabled! This will spam your console!\nTo disable this, unset the 'LOG_REQUESTS' environment variable!`));
+ app.use("/assets", express.static(path.join(ASSET_FOLDER_PATH, "public")));
+ app.use("/assets", express.static(path.join(ASSET_FOLDER_PATH, "cache")));
+
+ app.use("/assets/plugins", express.static(path.join(ASSET_FOLDER_PATH, "plugins")));
+ app.use("/assets/inline-plugins", express.static(path.join(ASSET_FOLDER_PATH, "inline-plugins")));
+
+ const assetCache = new Map();
+
+ // Fetches uncached ( on disk ) assets from discord.com and stores them in memory cache.
+ app.get("/assets/:file", async (req, res) => {
+ delete req.headers.host;
+
+ if (req.params.file.endsWith(".map")) return res.status(404);
+
+ let response: FetchResponse;
+ let buffer: Buffer;
+ const cache = assetCache.get(req.params.file);
+ if (!cache) {
+ response = await fetch(`https://discord.com/assets/${req.params.file}`, {
+ headers: { ...(req.headers as { [key: string]: string }) },
+ });
+ buffer = await response.buffer();
+ } else {
+ response = cache.response;
+ buffer = cache.buffer;
+ }
+
+ [
+ "content-length",
+ "content-security-policy",
+ "strict-transport-security",
+ "set-cookie",
+ "transfer-encoding",
+ "expect-ct",
+ "access-control-allow-origin",
+ "content-encoding",
+ ].forEach((headerName) => {
+ response.headers.delete(headerName);
+ });
+ response.headers.forEach((value, name) => res.set(name, value));
+
+ assetCache.set(req.params.file, { buffer, response });
+
+ // TODO: I don't like this. Figure out a way to get client cacher to download *all* assets.
+ if (response.status == 200) {
+ console.warn(`[TestClient] Cache miss for file ${req.params.file}! Use 'npm run generate:client' to cache and patch.`);
+ await fs.promises.appendFile(path.join(ASSET_FOLDER_PATH, "cacheMisses"), req.params.file + "\n");
+ }
+
+ return res.send(buffer);
+ });
+
+ app.use((req, res, next) => {
+ console.log(`[TestClient Wildcard] Intercepted path: ${req.url}`);
+
+ if (req.url.startsWith("/api") || req.url.startsWith("/__development")) {
+ console.log(`[TestClient Wildcard] Bypassing route (matched API guard): ${req.url}`);
+ return next ? next() : res.sendStatus(404);
+ }
+
+ console.log(`[TestClient Wildcard] Serving index.html for: ${req.url}`);
+ res.set("Cache-Control", "public, max-age=" + 60 * 60 * 24);
+ res.set("content-type", "text/html");
+
+ return res.send(html);
+ });
await ProcessLifecycle.Ready();
return super.start();
}
diff --git a/src/api/middlewares/TestClient.ts b/src/api/middlewares/TestClient.ts
new file mode 100644
index 0000000..3d5e44b
--- /dev/null
+++ b/src/api/middlewares/TestClient.ts
@@ -0,0 +1,144 @@
+import express, { Application } from "express";
+import fs from "node:fs";
+import path from "node:path";
+import fetch, { Response as FetchResponse, Headers } from "node-fetch";
+import { Config } from "@spacebar/util";
+
+const ASSET_FOLDER_PATH = path.join(__dirname, "..", "..", "..", "assets");
+
+export default function TestClient(app: Application) {
+ console.log("call");
+ app.use("/assets", express.static(path.join(ASSET_FOLDER_PATH, "public")));
+ app.use("/assets", express.static(path.join(ASSET_FOLDER_PATH, "cache")));
+ console.log("call 2");
+
+ let html = fs.readFileSync(path.join(ASSET_FOLDER_PATH, "client_test", "index.html"), { encoding: "utf-8" });
+ console.log("call 3");
+
+ html = applyEnv(html); // update window.GLOBAL_ENV according to config
+
+ html = applyPlugins(html); // inject our plugins
+ app.use("/assets/plugins", express.static(path.join(ASSET_FOLDER_PATH, "plugins")));
+ app.use("/assets/inline-plugins", express.static(path.join(ASSET_FOLDER_PATH, "inline-plugins")));
+
+ console.log("call 4");
+
+ // Asset memory cache
+ const assetCache = new Map();
+
+ // Fetches uncached ( on disk ) assets from discord.com and stores them in memory cache.
+ app.get("/assets/:file", async (req, res) => {
+ delete req.headers.host;
+
+ if (req.params.file.endsWith(".map")) return res.status(404);
+
+ let response: FetchResponse;
+ let buffer: Buffer;
+ const cache = assetCache.get(req.params.file);
+ if (!cache) {
+ response = await fetch(`https://discord.com/assets/${req.params.file}`, {
+ headers: { ...(req.headers as { [key: string]: string }) },
+ });
+ buffer = await response.buffer();
+ } else {
+ response = cache.response;
+ buffer = cache.buffer;
+ }
+
+ [
+ "content-length",
+ "content-security-policy",
+ "strict-transport-security",
+ "set-cookie",
+ "transfer-encoding",
+ "expect-ct",
+ "access-control-allow-origin",
+ "content-encoding",
+ ].forEach((headerName) => {
+ response.headers.delete(headerName);
+ });
+ response.headers.forEach((value, name) => res.set(name, value));
+
+ assetCache.set(req.params.file, { buffer, response });
+
+ // TODO: I don't like this. Figure out a way to get client cacher to download *all* assets.
+ if (response.status == 200) {
+ console.warn(`[TestClient] Cache miss for file ${req.params.file}! Use 'npm run generate:client' to cache and patch.`);
+ await fs.promises.appendFile(path.join(ASSET_FOLDER_PATH, "cacheMisses"), req.params.file + "\n");
+ }
+
+ return res.send(buffer);
+ });
+
+ console.log("call 5");
+
+ // Instead of our generated html, send developers.html for developers endpoint
+ app.get("/developers*", (req, res) => {
+ res.set("Cache-Control", "public, max-age=" + 60 * 60 * 24); // 24 hours
+ res.set("content-type", "text/html");
+ res.send(fs.readFileSync(path.join(ASSET_FOLDER_PATH, "client_test", "developers.html"), { encoding: "utf-8" }));
+ });
+
+ console.log("call 6");
+
+ // Send our generated index.html for all routes.
+ app.get("*", (req, res, next) => {
+ console.log(`[TestClient Wildcard] Intercepted path: ${req.url}`);
+
+ if (req.url.startsWith("/api") || req.url.startsWith("/__development")) {
+ console.log(`[TestClient Wildcard] Bypassing route (matched API guard): ${req.url}`);
+ return next ? next() : res.sendStatus(404);
+ }
+
+ console.log(`[TestClient Wildcard] Serving index.html for: ${req.url}`);
+ res.set("Cache-Control", "public, max-age=" + 60 * 60 * 24);
+ res.set("content-type", "text/html");
+
+ return res.send(html);
+ });
+ console.log("call 7");
+}
+
+// Apply gateway/cdn endpoint values from config to index.html.
+export const applyEnv = (html: string): string => {
+ const config = Config.get();
+
+ const cdn = (config.cdn.endpointClient || config.cdn.endpointPublic || process.env.CDN || "").replace(/(https?)?(:\/\/?)/g, "");
+
+ const gateway = config.gateway.endpointClient || config.gateway.endpointPublic || process.env.GATEWAY || "";
+
+ if (cdn) html = html.replace(/CDN_HOST: .+/, `CDN_HOST: \`${cdn}\`,`);
+
+ if (gateway) html = html.replace(/GATEWAY_ENDPOINT: .+/, `GATEWAY_ENDPOINT: \`${gateway}\`,`);
+
+ return html;
+};
+
+// Injects inline, preload, and standard plugins into index.html.
+export const applyPlugins = (html: string): string => {
+ // Inline plugins. Injected as `)
+ .join("\n");
+ html = html.replace("", inline);
+
+ // Preload plugins. Text content of each plugin is injected into head.
+ const preloadFiles = fs.readdirSync(path.join(ASSET_FOLDER_PATH, "preload-plugins"));
+ const preload = preloadFiles
+ .filter((x) => x.endsWith(".js"))
+ .map((x) => ``)
+ .join("\n");
+ html = html.replace("", preload);
+
+ // Normal plugins. Injected as `)
+ .join("\n");
+ html = html.replace("", plugins);
+
+ return html;
+};
diff --git a/src/util/config/types/ClientConfiguration.ts b/src/util/config/types/ClientConfiguration.ts
new file mode 100644
index 0000000..6434f15
--- /dev/null
+++ b/src/util/config/types/ClientConfiguration.ts
@@ -0,0 +1,24 @@
+/*
+ Fosscord: A FOSS re-implementation and extension of the Discord.com backend.
+ Copyright (C) 2023 Fosscord and Fosscord Contributors
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+
+import { ClientReleaseConfiguration } from ".";
+
+export class ClientConfiguration {
+ releases: ClientReleaseConfiguration = new ClientReleaseConfiguration();
+ useTestClient: boolean = true;
+}
diff --git a/src/util/config/types/EndpointConfiguration.ts b/src/util/config/types/EndpointConfiguration.ts
index b1bccd2..c9f69e9 100644
--- a/src/util/config/types/EndpointConfiguration.ts
+++ b/src/util/config/types/EndpointConfiguration.ts
@@ -17,6 +17,7 @@
*/
export class EndpointConfiguration {
+ endpointClient: string | null = null;
endpointPrivate: string | null = null;
endpointPublic: string | null = null;
}
diff --git a/src/util/config/types/subconfigurations/client/ClientReleaseConfiguration.ts b/src/util/config/types/subconfigurations/client/ClientReleaseConfiguration.ts
new file mode 100644
index 0000000..1765167
--- /dev/null
+++ b/src/util/config/types/subconfigurations/client/ClientReleaseConfiguration.ts
@@ -0,0 +1,22 @@
+/*
+ Fosscord: A FOSS re-implementation and extension of the Discord.com backend.
+ Copyright (C) 2023 Fosscord and Fosscord Contributors
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+
+export class ClientReleaseConfiguration {
+ useLocalRelease: boolean = true; //TODO
+ upstreamVersion: string = "0.0.264";
+}
diff --git a/src/util/config/types/subconfigurations/client/index.ts b/src/util/config/types/subconfigurations/client/index.ts
new file mode 100644
index 0000000..96bbb0c
--- /dev/null
+++ b/src/util/config/types/subconfigurations/client/index.ts
@@ -0,0 +1 @@
+export * from "./ClientReleaseConfiguration";
diff --git a/src/util/config/types/subconfigurations/index.ts b/src/util/config/types/subconfigurations/index.ts
index 82385df..f74a811 100644
--- a/src/util/config/types/subconfigurations/index.ts
+++ b/src/util/config/types/subconfigurations/index.ts
@@ -22,3 +22,4 @@
export * from "./limits";
export * from "./register";
export * from "./security";
+export * from "./client";