From 225ec3fb49a11dc1e4ce1e0c0d552c69a6732e57 Mon Sep 17 00:00:00 2001 From: localhost Date: Sat, 1 Nov 2025 22:42:00 +0100 Subject: [PATCH] add more parsable error pages --- bun.lockb | Bin 50300 -> 52131 bytes package.json | 1 + src/router/html.ts | 3 ++- src/router/latest.ts | 3 ++- src/router/search.ts | 3 ++- src/router/transparency.ts | 3 ++- src/router/video.ts | 3 ++- src/router/websocket.ts | 2 ++ src/utils/html.ts | 23 ++++++++++++++++++++++- 9 files changed, 35 insertions(+), 6 deletions(-) diff --git a/bun.lockb b/bun.lockb index b169c1549fa10e5cf8010a8172f875198d8d7114..8929e42552e10a1050cdd3136ecb5d5233a2020b 100755 GIT binary patch delta 7905 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 MY1`s>?~%)Y0TpXx4FCWD delta 6854 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 V!#mV=z&qePIMz9^@2CFv{Wnk$@CN_@ diff --git a/package.json b/package.json index b97df07..b99b926 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "@elysiajs/static": "^1.4.0", "@types/html-minifier-next": "^2.1.0", "@types/pg": "^8.11.10", + "age-encryption": "^0.2.4", "date-fns": "^4.1.0", "elysia": "^1.1.25", "eta": "^4.0.1", diff --git a/src/router/html.ts b/src/router/html.ts index a0c778e..1da7400 100644 --- a/src/router/html.ts +++ b/src/router/html.ts @@ -1,5 +1,5 @@ import { Elysia } from 'elysia'; -import { m, eta } from '@/utils/html' +import { m, eta, error } from '@/utils/html' const app = new Elysia() app.get('/', async ({ set }) => { @@ -65,4 +65,5 @@ app.get('/donate', async ({ set }) => { })) }) +app.onError(error) export default app; \ No newline at end of file diff --git a/src/router/latest.ts b/src/router/latest.ts index 73e08de..cf9ea2b 100644 --- a/src/router/latest.ts +++ b/src/router/latest.ts @@ -1,7 +1,7 @@ import { Elysia } from 'elysia'; import { db } from '@/utils/database' import { createSitemapXML, createSitemapIndexXML } from '@/utils/sitemap' -import { m, eta } from '@/utils/html' +import { m, eta, error } from '@/utils/html' import redis from '@/utils/redis'; const app = new Elysia() @@ -67,4 +67,5 @@ app.get('/sitemap-:index.xml', async ({ set, params: { index }, error, path }) = return error(404) }) +app.onError(error) export default app \ No newline at end of file diff --git a/src/router/search.ts b/src/router/search.ts index d85f1ae..76ba2b6 100644 --- a/src/router/search.ts +++ b/src/router/search.ts @@ -3,7 +3,7 @@ import { RedisRateLimiter } from 'rolling-rate-limiter' import { db } from '@/utils/database' import { validateVideo, validateChannel } from '@/utils/regex' -import { m, eta } from '@/utils/html' +import { m, eta, error } from '@/utils/html' import redis from '@/utils/redis'; const app = new Elysia() @@ -59,4 +59,5 @@ app.get('/search/channel', async ({ query: { url }, error, redirect }) => { }) }) +app.onError(error) export default app \ No newline at end of file diff --git a/src/router/transparency.ts b/src/router/transparency.ts index 974b57c..1af45ec 100644 --- a/src/router/transparency.ts +++ b/src/router/transparency.ts @@ -1,7 +1,7 @@ import { Elysia } from 'elysia'; import { db } from '@/utils/database' -import { m, eta } from '@/utils/html' +import { m, eta, error } from '@/utils/html' import redis from '@/utils/redis'; const app = new Elysia() @@ -52,4 +52,5 @@ app.get('/transparency/:id', async ({ params: { id }, set, error }) => { return html }) +app.onError(error) export default app \ No newline at end of file diff --git a/src/router/video.ts b/src/router/video.ts index 13711af..76283a5 100644 --- a/src/router/video.ts +++ b/src/router/video.ts @@ -4,7 +4,7 @@ import DOMPurify from 'isomorphic-dompurify' import { db } from '@/utils/database' import { getChannel, getChannelVideos } from '@/utils/metadata'; import { convertRelativeToDate } from '@/utils/common'; -import { m, eta } from '@/utils/html' +import { m, eta, error } from '@/utils/html' import redis from '@/utils/redis'; const app = new Elysia() @@ -170,4 +170,5 @@ app.get('/channel/:id/videos', async ({ params: { id }, set }) => { return html }) +app.onError(error) export default app \ No newline at end of file diff --git a/src/router/websocket.ts b/src/router/websocket.ts index 407faab..125cffd 100644 --- a/src/router/websocket.ts +++ b/src/router/websocket.ts @@ -7,6 +7,7 @@ import { checkCaptcha, createDatabaseVideo } from '@/utils/common'; import { downloadVideo } from '@/utils/download'; import { uploadVideo } from '@/utils/upload'; import { getChannelVideos } from '@/utils/metadata'; +import { error } from '@/utils/html' import redis from '@/utils/redis'; const app = new Elysia() @@ -182,4 +183,5 @@ app.ws('/savechannel', { } }) +app.onError(error) export default app \ No newline at end of file diff --git a/src/utils/html.ts b/src/utils/html.ts index c00f301..1789d6f 100644 --- a/src/utils/html.ts +++ b/src/utils/html.ts @@ -1,4 +1,5 @@ import { minify } from 'html-minifier-next'; +import * as age from 'age-encryption' import { Eta } from 'eta'; import path from 'path'; @@ -10,4 +11,24 @@ export const m = async (html: string) => { }) } -export const eta = new Eta({ views: path.join(__dirname, '../templates'), functionHeader: `const hostname = "${process.env.SERVER_NICKNAME}"` }) \ No newline at end of file +export const eta = new Eta({ views: path.join(__dirname, '../templates'), functionHeader: `const hostname = "${process.env.SERVER_NICKNAME}"` }) + +export const error = async ({ error }: any) => { + const debuggingInfo = { + serverNickname: process.env.SERVER_NICKNAME, + currentTime: new Date().toISOString(), + errorStack: error.stack + } + + const e = new age.Encrypter() // my public key + e.addRecipient('age19f5carv77e9m7m3egef6dhmj3ltj5t84eca42ag84yn2ljwv94tqmh8le4') + const ciphertext = await e.encrypt(JSON.stringify(debuggingInfo)) + const armored = age.armor.encode(ciphertext) + + return `you found a bug! ${error.message} + +does this error keep persiting? please report it to admin@preservetube.com with the following debugging info: +(please copy paste this entire page into the email) + +${armored}` +} \ No newline at end of file