From bec60fbf96b0cb3b099ac162ce7a58f9a2b32528 Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Tue, 27 Aug 2024 16:45:05 +0200 Subject: [PATCH] refactor(api): :fire: Remove Glitch-FE explicit support --- .gitignore | 4 - app.ts | 9 - biome.json | 12 +- config/config.example.toml | 10 +- config/config.schema.json | 32 -- docker-compose.yml | 1 - docs/glitch-soc.md | 37 --- docs/installation.md | 5 - package.json | 2 +- packages/config-manager/config.type.ts | 16 - packages/glitch-server/glitch-languages.ts | 210 ------------ packages/glitch-server/main.ts | 361 --------------------- 12 files changed, 8 insertions(+), 691 deletions(-) delete mode 100644 docs/glitch-soc.md delete mode 100644 packages/glitch-server/glitch-languages.ts delete mode 100644 packages/glitch-server/main.ts diff --git a/.gitignore b/.gitignore index 79f66ab2..389f31ad 100644 --- a/.gitignore +++ b/.gitignore @@ -179,10 +179,6 @@ log.txt *.log build config/extended_description_test.md -glitch-old -glitch -glitch.tar.gz -glitch-dev *.pem oclif.manifest.json .direnv/ diff --git a/app.ts b/app.ts index 54104069..f1d0696d 100644 --- a/app.ts +++ b/app.ts @@ -11,7 +11,6 @@ import { bait } from "./middlewares/bait"; import { boundaryCheck } from "./middlewares/boundary-check"; import { ipBans } from "./middlewares/ip-bans"; import { logger } from "./middlewares/logger"; -import { handleGlitchRequest } from "./packages/glitch-server/main"; import { routes } from "./routes"; import type { ApiRouteExports } from "./types/api"; @@ -102,14 +101,6 @@ export const appFactory = async () => { }); app.all("*", async (context) => { - if (config.frontend.glitch.enabled) { - const glitch = await handleGlitchRequest(context.req.raw); - - if (glitch) { - return glitch; - } - } - const replacedUrl = new URL( new URL(context.req.url).pathname, config.frontend.url, diff --git a/biome.json b/biome.json index 54bc9f4f..7a908ec3 100644 --- a/biome.json +++ b/biome.json @@ -1,8 +1,7 @@ { "$schema": "https://biomejs.dev/schemas/1.8.3/schema.json", "organizeImports": { - "enabled": true, - "ignore": ["node_modules", "dist", "glitch", "glitch-dev"] + "enabled": true }, "linter": { "enabled": true, @@ -62,16 +61,17 @@ "useImportExtensions": "off", "useThrowNewError": "warn" } - }, - "ignore": ["node_modules", "dist", "glitch", "glitch-dev"] + } }, "formatter": { "enabled": true, "indentStyle": "space", - "indentWidth": 4, - "ignore": ["node_modules", "dist", "glitch", "glitch-dev"] + "indentWidth": 4 }, "javascript": { "globals": ["Bun", "HTMLRewriter", "BufferEncoding"] + }, + "files": { + "ignore": ["node_modules", "dist"] } } diff --git a/config/config.example.toml b/config/config.example.toml index 03b384d4..0609357d 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -120,7 +120,7 @@ bait_ips = ["127.0.0.1", "::1"] bait_user_agents = ["curl", "wget"] [frontend] -# Enable custom frontends (warning: not enabling this or Glitch will make Versia Server only accessible via the Mastodon API) +# Enable custom frontends (warning: not enabling this will make Versia Server only accessible via the Mastodon API) # Frontends also control the OAuth flow, so if you disable this, you will need to use the Mastodon frontend enabled = true # The URL to reach the frontend at (should be on a local network) @@ -141,14 +141,6 @@ url = "http://localhost:3000" # This can be used to set up custom themes, etc on supported frontends. # theme = "dark" -[frontend.glitch] -# Enable the Glitch frontend integration -enabled = false -# Glitch assets folder -assets = "glitch" -# Server the assets were ripped from (and any eventual CDNs) -server = ["https://tech.lgbt"] - [smtp] # SMTP server to use for sending emails server = "smtp.example.com" diff --git a/config/config.schema.json b/config/config.schema.json index 089510ef..b6d18a95 100644 --- a/config/config.schema.json +++ b/config/config.schema.json @@ -392,33 +392,6 @@ "$ref": "#/properties/http/properties/proxy/properties/address/anyOf/0", "default": "http://localhost:3000" }, - "glitch": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "default": false - }, - "assets": { - "type": "string", - "minLength": 1, - "default": "glitch" - }, - "server": { - "type": "array", - "items": { - "$ref": "#/properties/http/properties/proxy/properties/address/anyOf/0" - }, - "default": [] - } - }, - "additionalProperties": false, - "default": { - "enabled": false, - "assets": "glitch", - "server": [] - } - }, "routes": { "type": "object", "properties": { @@ -463,11 +436,6 @@ "default": { "enabled": true, "url": "http://localhost:3000", - "glitch": { - "enabled": false, - "assets": "glitch", - "server": [] - }, "settings": {} } }, diff --git a/docker-compose.yml b/docker-compose.yml index 4ecec0bb..9bb0c89f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,7 +5,6 @@ services: - ./logs:/app/dist/logs - ./config:/app/dist/config - ./uploads:/app/dist/uploads - - ./glitch:/app/dist/glitch restart: unless-stopped container_name: versia command: "cli start --all-threads" diff --git a/docs/glitch-soc.md b/docs/glitch-soc.md deleted file mode 100644 index 6b277aa5..00000000 --- a/docs/glitch-soc.md +++ /dev/null @@ -1,37 +0,0 @@ -# Enabling Glitch-Soc - -Versia Server supports the use of the Glitch-Soc fork of Mastodon's frontend. Here's how to do it: - -1. Download the latest Glitch FE package from [the releases page](https://github.com/lysand-org/server/releases) (it should be named `glitch.tar.gz` and be inside the assets of a normal Versia Server release). -2. Extract the contents of the package into a folder, which you can name `glitch` for simplicity. (if using Docker, now is the time to mount that folder into the container, for example with `-v /path/to/glitch:/app/dist/glitch`) -3. Change the config to enable Glitch-FE: - ```toml - [frontend] - # Enable custom frontends (warning: not enabling this or Glitch will make Versia Server only accessible via the Mastodon API) - # Frontends also control the OAuth flow, so if you disable this, you will need to use the Mastodon frontend - enabled = true - # The URL to reach the frontend at (should be on a local network) - url = "http://localhost:3000" - - [frontend.glitch] - # Enable the Glitch frontend integration - enabled = true - # Glitch assets folder - assets = "glitch" - # Server the assets were ripped from (and any eventual CDNs) - server = ["https://tech.lgbt"] - ``` - The `server` option can be left as-is, unless you have downloaded your own `index.html` file from a different Glitch instance. -4. Start Versia Server and navigate to `/` to see the Glitch frontend in action. - -## How is this package created? - -Glitch-FE is a React single-page app, which dynamically creates an `index.html` file on every request and builds all the other assets at build time. - -The package static files were taken from a build of Glitch-Soc, while the index.html file was taken from [the tech.lgbt instance](https://tech.lgbt) with `cURL`. - -Then, the paths in the `index.html` file were replaced with the correct paths for the static files (as they have different hashes in their names from the ones in the Glitch-Soc build). - -At runtime, Versia Server dynamically edits the index.html file to replace the content with correct data, as well as disabling `integrity` checks on the script/link tags. - -In the future, I'll find a way to make this less hacky and more user-friendly, but for now, this is the best I can do. \ No newline at end of file diff --git a/docs/installation.md b/docs/installation.md index b700519d..c15ec82d 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -92,11 +92,6 @@ You may use the environment variables `NO_COLORS=true` and `NO_FANCY_DATES=true` Please see the [CLI documentation](cli.md) for more information on how to use the CLI. -> [!NOTE] -> You might be interested in running the [Glitch-Soc](glitch-soc.md) frontend, which is a fork of Mastodon's frontend with additional features. -> -> This is possible by following the instructions in [this file](glitch-soc.md). - ## Updating the server Updating the server is as simple as pulling the latest changes from the repository and running `bun prod-build` again. You may need to run `bun install` again if there are new dependencies. diff --git a/package.json b/package.json index 7ae47eb9..bb92b55d 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "start": "NODE_ENV=production bun run dist/index.js --prod", "lint": "bunx @biomejs/biome check .", "build": "bun run build.ts", - "cloc": "cloc . --exclude-dir node_modules,dist,.output,.nuxt,meta,logs,glitch,glitch-dev --exclude-ext sql,log,pem", + "cloc": "cloc . --exclude-dir node_modules,dist,.output,.nuxt,meta,logs --exclude-ext sql,log,pem", "wc": "find server database *.ts docs packages types utils drizzle tests -type f -print0 | wc -m --files0-from=-", "cli": "bun run cli/index.ts", "prune": "ts-prune | grep -v server/ | grep -v dist/ | grep -v '(used in module)'", diff --git a/packages/config-manager/config.type.ts b/packages/config-manager/config.type.ts index b1638684..f83636fa 100644 --- a/packages/config-manager/config.type.ts +++ b/packages/config-manager/config.type.ts @@ -182,17 +182,6 @@ export const configValidator = z.object({ .object({ enabled: z.boolean().default(true), url: zUrl.default("http://localhost:3000"), - glitch: z - .object({ - enabled: z.boolean().default(false), - assets: z.string().min(1).default("glitch"), - server: z.array(zUrl).default([]), - }) - .default({ - enabled: false, - assets: "glitch", - server: [], - }), routes: z .object({ home: zUrlPath.default("/"), @@ -213,11 +202,6 @@ export const configValidator = z.object({ .default({ enabled: true, url: "http://localhost:3000", - glitch: { - enabled: false, - assets: "glitch", - server: [], - }, settings: {}, }), smtp: z diff --git a/packages/glitch-server/glitch-languages.ts b/packages/glitch-server/glitch-languages.ts deleted file mode 100644 index 2b44d1b7..00000000 --- a/packages/glitch-server/glitch-languages.ts +++ /dev/null @@ -1,210 +0,0 @@ -export const languages = [ - ["aa", "Afar", "Afaraf"], - ["ab", "Abkhaz", "аҧсуа бызшәа"], - ["ae", "Avestan", "avesta"], - ["af", "Afrikaans", "Afrikaans"], - ["ak", "Akan", "Akan"], - ["am", "Amharic", "አማርኛ"], - ["an", "Aragonese", "aragonés"], - ["ar", "Arabic", "اللغة العربية"], - ["as", "Assamese", "অসমীয়া"], - ["av", "Avaric", "авар мацӀ"], - ["ay", "Aymara", "aymar aru"], - ["az", "Azerbaijani", "azərbaycan dili"], - ["ba", "Bashkir", "башҡорт теле"], - ["be", "Belarusian", "беларуская мова"], - ["bg", "Bulgarian", "български език"], - ["bh", "Bihari", "भोजपुरी"], - ["bi", "Bislama", "Bislama"], - ["bm", "Bambara", "bamanankan"], - ["bn", "Bengali", "বাংলা"], - ["bo", "Tibetan", "བོད་ཡིག"], - ["br", "Breton", "brezhoneg"], - ["bs", "Bosnian", "bosanski jezik"], - ["ca", "Catalan", "Català"], - ["ce", "Chechen", "нохчийн мотт"], - ["ch", "Chamorro", "Chamoru"], - ["co", "Corsican", "corsu"], - ["cr", "Cree", "ᓀᐦᐃᔭᐍᐏᐣ"], - ["cs", "Czech", "čeština"], - ["cu", "Old Church Slavonic", "ѩзыкъ словѣньскъ"], - ["cv", "Chuvash", "чӑваш чӗлхи"], - ["cy", "Welsh", "Cymraeg"], - ["da", "Danish", "dansk"], - ["de", "German", "Deutsch"], - ["dv", "Divehi", "Dhivehi"], - ["dz", "Dzongkha", "རྫོང་ཁ"], - ["ee", "Ewe", "Eʋegbe"], - ["el", "Greek", "Ελληνικά"], - ["en", "English", "English"], - ["eo", "Esperanto", "Esperanto"], - ["es", "Spanish", "Español"], - ["et", "Estonian", "eesti"], - ["eu", "Basque", "euskara"], - ["fa", "Persian", "فارسی"], - ["ff", "Fula", "Fulfulde"], - ["fi", "Finnish", "suomi"], - ["fj", "Fijian", "Vakaviti"], - ["fo", "Faroese", "føroyskt"], - ["fr", "French", "Français"], - ["fy", "Western Frisian", "Frysk"], - ["ga", "Irish", "Gaeilge"], - ["gd", "Scottish Gaelic", "Gàidhlig"], - ["gl", "Galician", "galego"], - ["gu", "Gujarati", "ગુજરાતી"], - ["gv", "Manx", "Gaelg"], - ["ha", "Hausa", "هَوُسَ"], - ["he", "Hebrew", "עברית"], - ["hi", "Hindi", "हिन्दी"], - ["ho", "Hiri Motu", "Hiri Motu"], - ["hr", "Croatian", "Hrvatski"], - ["ht", "Haitian", "Kreyòl ayisyen"], - ["hu", "Hungarian", "magyar"], - ["hy", "Armenian", "Հայերեն"], - ["hz", "Herero", "Otjiherero"], - ["ia", "Interlingua", "Interlingua"], - ["id", "Indonesian", "Bahasa Indonesia"], - ["ie", "Interlingue", "Interlingue"], - ["ig", "Igbo", "Asụsụ Igbo"], - ["ii", "Nuosu", "ꆈꌠ꒿ Nuosuhxop"], - ["ik", "Inupiaq", "Iñupiaq"], - ["io", "Ido", "Ido"], - ["is", "Icelandic", "Íslenska"], - ["it", "Italian", "Italiano"], - ["iu", "Inuktitut", "ᐃᓄᒃᑎᑐᑦ"], - ["ja", "Japanese", "日本語"], - ["jv", "Javanese", "basa Jawa"], - ["ka", "Georgian", "ქართული"], - ["kg", "Kongo", "Kikongo"], - ["ki", "Kikuyu", "Gĩkũyũ"], - ["kj", "Kwanyama", "Kuanyama"], - ["kk", "Kazakh", "қазақ тілі"], - ["kl", "Kalaallisut", "kalaallisut"], - ["km", "Khmer", "ខេមរភាសា"], - ["kn", "Kannada", "ಕನ್ನಡ"], - ["ko", "Korean", "한국어"], - ["kr", "Kanuri", "Kanuri"], - ["ks", "Kashmiri", "कश्मीरी"], - ["ku", "Kurmanji (Kurdish)", "Kurmancî"], - ["kv", "Komi", "коми кыв"], - ["kw", "Cornish", "Kernewek"], - ["ky", "Kyrgyz", "Кыргызча"], - ["la", "Latin", "latine"], - ["lb", "Luxembourgish", "Lëtzebuergesch"], - ["lg", "Ganda", "Luganda"], - ["li", "Limburgish", "Limburgs"], - ["ln", "Lingala", "Lingála"], - ["lo", "Lao", "ລາວ"], - ["lt", "Lithuanian", "lietuvių kalba"], - ["lu", "Luba-Katanga", "Tshiluba"], - ["lv", "Latvian", "latviešu valoda"], - ["mg", "Malagasy", "fiteny malagasy"], - ["mh", "Marshallese", "Kajin M̧ajeļ"], - ["mi", "Māori", "te reo Māori"], - ["mk", "Macedonian", "македонски јазик"], - ["ml", "Malayalam", "മലയാളം"], - ["mn", "Mongolian", "Монгол хэл"], - ["mr", "Marathi", "मराठी"], - ["ms", "Malay", "Bahasa Melayu"], - ["ms-Arab", "Jawi Malay", "بهاس ملايو"], - ["mt", "Maltese", "Malti"], - ["my", "Burmese", "ဗမာစာ"], - ["na", "Nauru", "Ekakairũ Naoero"], - ["nb", "Norwegian Bokmål", "Norsk bokmål"], - ["nd", "Northern Ndebele", "isiNdebele"], - ["ne", "Nepali", "नेपाली"], - ["ng", "Ndonga", "Owambo"], - ["nl", "Dutch", "Nederlands"], - ["nn", "Norwegian Nynorsk", "Norsk Nynorsk"], - ["no", "Norwegian", "Norsk"], - ["nr", "Southern Ndebele", "isiNdebele"], - ["nv", "Navajo", "Diné bizaad"], - ["ny", "Chichewa", "chiCheŵa"], - ["oc", "Occitan", "occitan"], - ["oj", "Ojibwe", "ᐊᓂᔑᓈᐯᒧᐎᓐ"], - ["om", "Oromo", "Afaan Oromoo"], - ["or", "Oriya", "ଓଡ଼ିଆ"], - ["os", "Ossetian", "ирон æвзаг"], - ["pa", "Punjabi", "ਪੰਜਾਬੀ"], - ["pi", "Pāli", "पाऴि"], - ["pl", "Polish", "Polski"], - ["ps", "Pashto", "پښتو"], - ["pt", "Portuguese", "Português"], - ["qu", "Quechua", "Runa Simi"], - ["rm", "Romansh", "rumantsch grischun"], - ["rn", "Kirundi", "Ikirundi"], - ["ro", "Romanian", "Română"], - ["ru", "Russian", "Русский"], - ["rw", "Kinyarwanda", "Ikinyarwanda"], - ["sa", "Sanskrit", "संस्कृतम्"], - ["sc", "Sardinian", "sardu"], - ["sd", "Sindhi", "सिन्धी"], - ["se", "Northern Sami", "Davvisámegiella"], - ["sg", "Sango", "yângâ tî sängö"], - ["si", "Sinhala", "සිංහල"], - ["sk", "Slovak", "slovenčina"], - ["sl", "Slovenian", "slovenščina"], - ["sn", "Shona", "chiShona"], - ["so", "Somali", "Soomaaliga"], - ["sq", "Albanian", "Shqip"], - ["sr", "Serbian", "српски језик"], - ["ss", "Swati", "SiSwati"], - ["st", "Southern Sotho", "Sesotho"], - ["su", "Sundanese", "Basa Sunda"], - ["sv", "Swedish", "Svenska"], - ["sw", "Swahili", "Kiswahili"], - ["ta", "Tamil", "தமிழ்"], - ["te", "Telugu", "తెలుగు"], - ["tg", "Tajik", "тоҷикӣ"], - ["th", "Thai", "ไทย"], - ["ti", "Tigrinya", "ትግርኛ"], - ["tk", "Turkmen", "Türkmen"], - ["tl", "Tagalog", "Wikang Tagalog"], - ["tn", "Tswana", "Setswana"], - ["to", "Tonga", "faka Tonga"], - ["tr", "Turkish", "Türkçe"], - ["ts", "Tsonga", "Xitsonga"], - ["tt", "Tatar", "татар теле"], - ["tw", "Twi", "Twi"], - ["ty", "Tahitian", "Reo Tahiti"], - ["ug", "Uyghur", "ئۇيغۇرچە‎"], - ["uk", "Ukrainian", "Українська"], - ["ur", "Urdu", "اردو"], - ["uz", "Uzbek", "Ўзбек"], - ["ve", "Venda", "Tshivenḓa"], - ["vi", "Vietnamese", "Tiếng Việt"], - ["vo", "Volapük", "Volapük"], - ["wa", "Walloon", "walon"], - ["wo", "Wolof", "Wollof"], - ["xh", "Xhosa", "isiXhosa"], - ["yi", "Yiddish", "ייִדיש"], - ["yo", "Yoruba", "Yorùbá"], - ["za", "Zhuang", "Saɯ cueŋƅ"], - ["zh", "Chinese", "中文"], - ["zu", "Zulu", "isiZulu"], - ["zh-CN", "Chinese (China)", "简体中文"], - ["zh-HK", "Chinese (Hong Kong)", "繁體中文(香港)"], - ["zh-TW", "Chinese (Taiwan)", "繁體中文(臺灣)"], - ["zh-YUE", "Cantonese", "廣東話"], - ["ast", "Asturian", "Asturianu"], - ["chr", "Cherokee", "ᏣᎳᎩ ᎦᏬᏂᎯᏍᏗ"], - ["ckb", "Sorani (Kurdish)", "سۆرانی"], - ["cnr", "Montenegrin", "crnogorski"], - ["csb", "Kashubian", "Kaszëbsczi"], - ["jbo", "Lojban", "la .lojban."], - ["kab", "Kabyle", "Taqbaylit"], - ["ldn", "Láadan", "Láadan"], - ["lfn", "Lingua Franca Nova", "lingua franca nova"], - ["moh", "Mohawk", "Kanienʼkéha"], - ["nds", "Low German", "Plattdüütsch"], - ["pdc", "Pennsylvania Dutch", "Pennsilfaani-Deitsch"], - ["sco", "Scots", "Scots"], - ["sma", "Southern Sami", "Åarjelsaemien Gïele"], - ["smj", "Lule Sami", "Julevsámegiella"], - ["szl", "Silesian", "ślůnsko godka"], - ["tok", "Toki Pona", "toki pona"], - ["vai", "Vai", "ꕙꔤ"], - ["xal", "Kalmyk", "Хальмг келн"], - ["zba", "Balaibalan", "باليبلن"], - ["zgh", "Standard Moroccan Tamazight", "ⵜⴰⵎⴰⵣⵉⵖⵜ"], -]; diff --git a/packages/glitch-server/main.ts b/packages/glitch-server/main.ts deleted file mode 100644 index 5eeef968..00000000 --- a/packages/glitch-server/main.ts +++ /dev/null @@ -1,361 +0,0 @@ -import { join } from "node:path"; -import { redirect } from "@/response"; -import type { BunFile } from "bun"; -import { retrieveUserFromToken } from "~/classes/functions/user"; -import { config } from "~/packages/config-manager/index"; -import type { User } from "~/packages/database-interface/user"; -import { languages } from "./glitch-languages"; - -const handleManifestRequest = () => { - const manifest = { - id: "/home", - name: config.instance.name, - short_name: config.instance.name, - icons: [ - { - src: "/packs/media/icons/android-chrome-36x36-e67f2bc645cc669c04ffcbc17203aeac.png", - sizes: "36x36", - type: "image/png", - purpose: "any maskable", - }, - { - src: "/packs/media/icons/android-chrome-48x48-d3afc36e9388913fb6add2476a556f67.png", - sizes: "48x48", - type: "image/png", - purpose: "any maskable", - }, - { - src: "/packs/media/icons/android-chrome-72x72-23ee104da45dc5388d59b8b0fad866f2.png", - sizes: "72x72", - type: "image/png", - purpose: "any maskable", - }, - { - src: "/packs/media/icons/android-chrome-96x96-fb2abfd885ab5de94025e09f6f9408b5.png", - sizes: "96x96", - type: "image/png", - purpose: "any maskable", - }, - { - src: "/packs/media/icons/android-chrome-144x144-99b386f89a3a2a22440964eba3b9f242.png", - sizes: "144x144", - type: "image/png", - purpose: "any maskable", - }, - { - src: "/packs/media/icons/android-chrome-192x192-8b4d35fdd9b5fa4592056ce687c9d0ba.png", - sizes: "192x192", - type: "image/png", - purpose: "any maskable", - }, - { - src: "/packs/media/icons/android-chrome-256x256-fecf6504157e3b195dd0e604cd711730.png", - sizes: "256x256", - type: "image/png", - purpose: "any maskable", - }, - { - src: "/packs/media/icons/android-chrome-384x384-dc559d916be51de4965dd7b8abf9c7c8.png", - sizes: "384x384", - type: "image/png", - purpose: "any maskable", - }, - { - src: "/packs/media/icons/android-chrome-512x512-85515d059c83f47d8e77e0703ebb7ff5.png", - sizes: "512x512", - type: "image/png", - purpose: "any maskable", - }, - ], - theme_color: "#191b22", - background_color: "#191b22", - display: "standalone", - start_url: "/", - scope: "/", - share_target: { - url_template: "share?title={title}\u0026text={text}\u0026url={url}", - action: "share", - method: "GET", - enctype: "application/x-www-form-urlencoded", - params: { title: "title", text: "text", url: "url" }, - }, - shortcuts: [ - { name: "Compose new post", url: "/publish" }, - { name: "Notifications", url: "/notifications" }, - { name: "Explore", url: "/explore" }, - ], - }; - - return new Response(JSON.stringify(manifest), { - headers: { - "Content-Type": "application/json; charset=utf-8", - "Content-Length": String(JSON.stringify(manifest).length), - "Cache-Control": "max-age=31536000", - Date: new Date().toUTCString(), - }, - }); -}; - -const handleSignInRequest = async ( - req: Request, - _path: string, - url: URL, - user: User | null, - accessToken: string, -) => { - if (req.method === "POST") { - if (url.searchParams.get("error")) { - const fileContents = await Bun.file( - join(config.frontend.glitch.assets, "/auth/sign_in.html"), - ).text(); - - // Insert error message as first child of form.form_container - const rewriter = new HTMLRewriter() - .on("div.form-container", { - element(element) { - element.prepend( - `
- ${decodeURIComponent( - url.searchParams.get("error") ?? "", - )} -
`, - { - html: true, - }, - ); - }, - }) - .transform(new Response(fileContents)); - - return returnFile( - Bun.file( - join(config.frontend.glitch.assets, "/auth/sign_in.html"), - ), - await brandingTransforms( - await rewriter.text(), - accessToken, - user, - ), - ); - } - return redirect("/api/auth/mastodon-login", 307); - } - - const file = Bun.file( - join(config.frontend.glitch.assets, "/auth/sign_in.html"), - ); - - return returnFile( - file, - await htmlTransforms( - await brandingTransforms(await file.text(), accessToken, user), - accessToken, - user, - ), - ); -}; - -const handleSignOutRequest = (req: Request) => { - if (req.method === "POST") { - return redirect("/api/auth/mastodon-logout", 307); - } - - return redirect("/", 307); -}; - -const returnFile = async (file: BunFile, content?: string) => { - return new Response(content ?? (await file.text()), { - headers: { - "Content-Type": `${file.type}; charset=utf-8`, - "Content-Length": String(file.size), - "Cache-Control": "max-age=31536000", - Date: new Date().toUTCString(), - }, - }); -}; - -const handleDefaultRequest = async ( - _req: Request, - path: string, - user: User | null, - accessToken: string, -) => { - const file = Bun.file(join(config.frontend.glitch.assets, path)); - - if (await file.exists()) { - const transformedText = await brandingTransforms( - path.endsWith(".html") - ? await htmlTransforms(await file.text(), accessToken, user) - : await file.text(), - accessToken, - user, - ); - - return returnFile(file, transformedText); - } - - return null; -}; - -const brandingTransforms = ( - fileContents: string, - _accessToken: string, - _user: User | null, -) => { - let newFileContents = fileContents; - for (const server of config.frontend.glitch.server) { - newFileContents = newFileContents.replaceAll( - `${new URL(server).origin}/`, - "/", - ); - newFileContents = newFileContents.replaceAll( - new URL(server).host, - new URL(config.http.base_url).host, - ); - } - - newFileContents = newFileContents.replaceAll( - "Glitch-soc is free open source software forked from Mastodon.", - "Versia Server is free and open-source software using the Glitch-Soc frontend.", - ); - newFileContents = newFileContents.replaceAll("Mastodon", "Versia Server"); - newFileContents = newFileContents.replaceAll( - "Versia is free, open-source software, and a trademark of Versia gGmbH.", - "This is not a Mastodon instance.", - ); - - newFileContents = newFileContents.replaceAll( - "joinmastodon.org", - "versia.pub", - ); - - return newFileContents; -}; - -const htmlTransforms = async ( - fileContents: string, - accessToken: string, - user: User | null, -) => { - // Find script id="initial-state" and replace its contents with custom json - const rewriter = new HTMLRewriter() - .on("script#initial-state", { - element(element) { - element.setInnerContent( - JSON.stringify({ - meta: { - access_token: accessToken || null, - activity_api_enabled: true, - admin: null, - domain: new URL(config.http.base_url).host, - limited_federation_mode: false, - locale: "en", - mascot: "https://media.tech.lgbt/site_uploads/files/000/000/004/original/1a16a73feb5c2463.png", - profile_directory: true, - registrations_open: true, - repository: "lysand-org/server", - search_enabled: true, - single_user_mode: false, - source_url: "https://github.com/lysand-org/server", - sso_redirect: null, - status_page_url: null, - streaming_api_base_url: `wss://${ - new URL(config.http.base_url).host - }`, - timeline_preview: true, - title: config.instance.name, - trends_as_landing_page: false, - trends_enabled: true, - version: "4.3.0-alpha.3+glitch", - auto_play_gif: null, - display_media: null, - reduce_motion: null, - use_blurhash: null, - me: user ? user.id : undefined, - }, - compose: user - ? { - text: "", - me: user.id, - default_privacy: "public", - default_sensitive: false, - default_language: "en", - } - : { - text: "", - }, - accounts: user - ? { - [user.id]: user.toApi(true), - } - : {}, - media_attachments: { - accept_content_types: - config.validation.allowed_mime_types, - }, - settings: {}, - max_feed_hashtags: 4, - poll_limits: { - max_options: config.validation.max_poll_options, - max_option_chars: - config.validation.max_poll_option_size, - min_expiration: config.validation.min_poll_duration, - max_expiration: config.validation.max_poll_duration, - }, - languages: languages, - push_subscription: null, - role: null, - }), - ); - }, - }) - .on("script", { - element(element) { - element.removeAttribute("integrity"); - }, - }) - .on("link", { - element(element) { - element.removeAttribute("integrity"); - }, - }) - .transform(new Response(fileContents)); - - return rewriter.text(); -}; - -export const handleGlitchRequest = async ( - req: Request, -): Promise => { - const url = new URL(req.url); - let path = url.pathname; - const accessToken = - req.headers.get("Cookie")?.match(/_session_id=(.*?)(;|$)/)?.[1] ?? ""; - const user = await retrieveUserFromToken(accessToken ?? ""); - - // Strip leading /web from path - if (path.startsWith("/web")) { - path = path.slice(4); - } - - if (path === "/manifest") { - return handleManifestRequest(); - } - - if (path === "/auth/sign_in") { - return handleSignInRequest(req, path, url, user, accessToken); - } - - if (path === "/auth/sign_out") { - return handleSignOutRequest(req); - } - - if ( - req.headers.get("Accept")?.includes("text/html") && - !path.includes(".") - ) { - path = "/index.html"; - } - - return handleDefaultRequest(req, path, user, accessToken); -};