mirror of
https://github.com/versia-pub/server.git
synced 2025-12-06 00:18:19 +01:00
refactor(api): 🔥 Remove Glitch-FE explicit support
This commit is contained in:
parent
df466ecaa0
commit
bec60fbf96
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -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/
|
||||
|
|
|
|||
9
app.ts
9
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,
|
||||
|
|
|
|||
12
biome.json
12
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"]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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": {}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)'",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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", "ⵜⴰⵎⴰⵣⵉⵖⵜ"],
|
||||
];
|
||||
|
|
@ -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(
|
||||
` <div class='flash-message alert'>
|
||||
<strong>${decodeURIComponent(
|
||||
url.searchParams.get("error") ?? "",
|
||||
)}</strong>
|
||||
</div>`,
|
||||
{
|
||||
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<Response | null> => {
|
||||
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);
|
||||
};
|
||||
Loading…
Reference in a new issue