From aab9d6251f04461047c51d840b3c1fb5a5c8f634 Mon Sep 17 00:00:00 2001 From: localhost Date: Mon, 17 Nov 2025 20:09:16 +0100 Subject: [PATCH] add health checking metadata, ios errors --- src/router/html.ts | 15 +++++++++++++-- src/templates/save.eta | 4 ++++ src/templates/savechannel.eta | 4 ++++ src/templates/watch.eta | 19 +++++++++++++++---- src/utils/health.ts | 20 ++++++++++++++++++++ 5 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 src/utils/health.ts diff --git a/src/router/html.ts b/src/router/html.ts index 6492ef4..2eb671f 100644 --- a/src/router/html.ts +++ b/src/router/html.ts @@ -1,5 +1,6 @@ import { Elysia } from 'elysia'; import { m, eta, error } from '@/utils/html' +import healthStatus from '@/utils/health'; const app = new Elysia() app.get('/', async ({ set }) => { @@ -14,10 +15,15 @@ app.get('/', async ({ set }) => { app.get('/save', async ({ query: { url }, set, error }) => { if (!url) return error(400, 'No url provided.') + let websocket = process.env.WEBSOCKET + if (healthStatus[process.env.METADATA!] != 'healthy') { + websocket = process.env.ALTERNATIVE_WEBSOCKET! + } + set.headers['Content-Type'] = 'text/html; charset=utf-8' return await m(eta.render('./save', { title: 'Save Video | PreserveTube', - websocket: process.env.WEBSOCKET, + websocket, sitekey: process.env.SITEKEY, url })) @@ -26,10 +32,15 @@ app.get('/save', async ({ query: { url }, set, error }) => { app.get('/savechannel', async ({ query: { url }, set, error }) => { if (!url) return error(400, 'No url provided.') + let websocket = process.env.WEBSOCKET + if (healthStatus[process.env.METADATA!] != 'healthy') { + websocket = process.env.ALTERNATIVE_WEBSOCKET! + } + set.headers['Content-Type'] = 'text/html; charset=utf-8' return await m(eta.render('./savechannel', { title: 'Save Channel | PreserveTube', - websocket: process.env.WEBSOCKET, + websocket, sitekey: process.env.SITEKEY, url })) diff --git a/src/templates/save.eta b/src/templates/save.eta index d71c9d3..3e0299a 100644 --- a/src/templates/save.eta +++ b/src/templates/save.eta @@ -21,6 +21,10 @@ const h3 = document.getElementById("bottom") const captcha = document.getElementById("captcha") + ws.onopen = function () { + document.querySelector("footer").innerHTML = `page rendered by <%= hostname %>, connected via ${websocket.split('-')[1].split('.')[0]}` + } + ws.onmessage = function (msg) { const text = msg.data.split(' - ').slice(1).join(' - ') diff --git a/src/templates/savechannel.eta b/src/templates/savechannel.eta index 997b100..1f58e4f 100644 --- a/src/templates/savechannel.eta +++ b/src/templates/savechannel.eta @@ -18,6 +18,10 @@ const h3 = document.getElementById("bottom") const captcha = document.getElementById("captcha") + ws.onopen = function () { + document.querySelector("footer").innerHTML = `page rendered by <%= hostname %>, connected via ${websocket.split('-')[1].split('.')[0]}` + } + ws.onmessage = function (msg) { const text = msg.data.split(' - ').slice(1).join(' - ') diff --git a/src/templates/watch.eta b/src/templates/watch.eta index 8b7e9d8..d6d85fa 100644 --- a/src/templates/watch.eta +++ b/src/templates/watch.eta @@ -218,6 +218,10 @@ function initVideoLoading() { const video = document.getElementById('video-player'); const loading = document.getElementById('video-loading'); + let hasTheVideoErrored = false + const isIOSOrIPad = /iPad|iPhone|iPod/.test(navigator.userAgent) || + (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1); + if (!video || !loading) return; loading?.classList.remove("hidden"); @@ -239,10 +243,17 @@ video.addEventListener('pointerdown', hide); video.addEventListener('error', () => { + hasTheVideoErrored = true loading.innerHTML = 'Video failed to load.'; - loading.innerHTML += '

This is not supposed to happen. Please email me at admin@preservetube.com with as much debugging information.

' + - '

Please include your browser console logs. ' + - 'See here on how to access them. Please note you might have to refresh the page for anything to show up.

' + + if (isIOSOrIPad) { + loading.innerHTML += '

It looks like you\'re on an iOS or iPadOS device. Apple devices without a hardware decoder can\'t play the kind of video Preservetube serves.

' + + '

Please try using a different device.

' + } else { + loading.innerHTML += '

This is not supposed to happen. Please email me at admin@preservetube.com with as much debugging information.

' + + '

Please include your browser console logs. ' + + 'See here on how to access them. Please note you might have to refresh the page for anything to show up.

' + } }); // video already has data (i.e. cached) @@ -251,7 +262,7 @@ // add an extra message after 10s const FALLBACK_MS = 10000; const fallbackTimer = setTimeout(() => { - if (!loading.classList.contains('hidden')) { + if (!loading.classList.contains('hidden') && !hasTheVideoErrored) { loading.innerHTML = 'Taking longer than usual to load...'; loading.innerHTML += '

This might be due one of multiple reasons:

' + '
  1. This video is large. Depending on your browser, it might try loading the full thing at one time, which will slow things down.
  2. ' diff --git a/src/utils/health.ts b/src/utils/health.ts new file mode 100644 index 0000000..8315845 --- /dev/null +++ b/src/utils/health.ts @@ -0,0 +1,20 @@ +const healthStatus: Record = {} + +async function checkHealth() { + const metadataServers: string[] = [process.env.METADATA!, process.env.ALTERNATIVE_METADATA!] + await Promise.all(metadataServers.map(async (m) => { + try { + const req = await fetch(m + '/health') + healthStatus[m] = req.ok ? 'healthy' : 'unhealthy' + } catch (_) { + healthStatus[m] = 'unhealthy' + } + })) + + console.log(`checked health status - ${Object.entries(healthStatus).map(h => `${h[0].split('-')[1].split('.')[0]} ${h[1]}`).join(', ')}`) +} + +checkHealth() +setInterval(checkHealth, 5 * 60000) + +export default healthStatus \ No newline at end of file