From c3c2f53960cdb4c62c66a0f8876d33497056d4f3 Mon Sep 17 00:00:00 2001 From: WardPearce Date: Tue, 2 Apr 2024 09:44:17 +1300 Subject: [PATCH 1/2] Improved error handling --- materialious/src/lib/Api/index.ts | 68 +++++++++++-------- materialious/src/routes/+layout.svelte | 6 +- .../src/routes/channel/[slug]/+page.ts | 11 ++- materialious/src/routes/history/+page.svelte | 19 ++++-- .../src/routes/playlist/[slug]/+page.ts | 10 ++- materialious/src/routes/playlists/+page.ts | 9 ++- .../src/routes/search/[slug]/+page.ts | 12 +++- .../src/routes/subscriptions/+page.ts | 13 ++-- materialious/src/routes/trending/+page.ts | 14 ++-- .../src/routes/watch/[slug]/+page.svelte | 6 ++ materialious/src/routes/watch/[slug]/+page.ts | 10 +-- 11 files changed, 118 insertions(+), 60 deletions(-) diff --git a/materialious/src/lib/Api/index.ts b/materialious/src/lib/Api/index.ts index 7d351342..f0a67105 100644 --- a/materialious/src/lib/Api/index.ts +++ b/materialious/src/lib/Api/index.ts @@ -6,27 +6,40 @@ export function buildPath(path: string): string { return `${import.meta.env.VITE_DEFAULT_INVIDIOUS_INSTANCE}/api/v1/${path}`; } +export async function fetchErrorHandle(response: Response): Promise { + if (!response.ok) { + let message = 'Internal error'; + try { + const json = await response.json(); + message = 'errorBacktrace' in json ? json.errorBacktrace : json.error; + } catch { } + throw Error(message); + } + + return response; +} + export function buildAuthHeaders(): { headers: { Authorization: string; }; } { return { headers: { Authorization: `Bearer ${get(auth)?.token}` } }; } export async function getTrending(): Promise { - const resp = await fetch(buildPath('trending')); + const resp = await fetchErrorHandle(await fetch(buildPath('trending'))); return await resp.json(); } export async function getPopular(): Promise { - const resp = await fetch(buildPath('popular')); + const resp = await fetchErrorHandle(await fetch(buildPath('popular'))); return await resp.json(); } export async function getVideo(videoId: string, local: boolean = false): Promise { - const resp = await fetch(buildPath(`videos/${videoId}?local=${local}`)); + const resp = await fetchErrorHandle(await fetch(buildPath(`videos/${videoId}?local=${local}`))); return await resp.json(); } export async function getDislikes(videoId: string): Promise { - const resp = await fetch(`${get(returnYTDislikesInstance)}/votes?videoId=${videoId}`); + const resp = await fetchErrorHandle(await fetch(`${get(returnYTDislikesInstance)}/votes?videoId=${videoId}`)); return await resp.json(); } @@ -45,12 +58,12 @@ export async function getComments(videoId: string, parameters: { const path = new URL(buildPath(`comments/${videoId}`)); path.search = new URLSearchParams(parameters).toString(); - const resp = await fetch(path); + const resp = await fetchErrorHandle(await fetch(path)); return await resp.json(); } export async function getChannel(channelId: string): Promise { - const resp = await fetch(buildPath(`channels/${channelId}`)); + const resp = await fetchErrorHandle(await fetch(buildPath(`channels/${channelId}`))); return await resp.json(); } @@ -66,14 +79,14 @@ export async function getChannelContent( if (typeof parameters.continuation !== 'undefined') url.searchParams.set('continuation', parameters.continuation); - const resp = await fetch(url.toString()); + const resp = await fetchErrorHandle(await fetch(url.toString())); return await resp.json(); } export async function getSearchSuggestions(search: string): Promise { const path = new URL(buildPath("search/suggestions")); path.search = new URLSearchParams({ q: search }).toString(); - const resp = await fetch(path); + const resp = await fetchErrorHandle(await fetch(path)); return await resp.json(); } @@ -96,19 +109,19 @@ export async function getSearch(search: string, options: { const path = new URL(buildPath("search")); path.search = new URLSearchParams({ ...options, q: search }).toString(); - const resp = await fetch(path); + const resp = await fetchErrorHandle(await fetch(path)); return await resp.json(); } export async function getFeed(maxResults: number, page: number) { const path = new URL(buildPath("auth/feed")); path.search = new URLSearchParams({ max_results: maxResults.toString(), page: page.toString() }).toString(); - const resp = await fetch(path, buildAuthHeaders()); + const resp = await fetchErrorHandle(await fetch(path, buildAuthHeaders())); return await resp.json(); } export async function getSubscriptions(): Promise { - const resp = await fetch(buildPath("auth/subscriptions"), buildAuthHeaders()); + const resp = await fetchErrorHandle(await fetch(buildPath("auth/subscriptions"), buildAuthHeaders())); return await resp.json(); } @@ -122,21 +135,21 @@ export async function amSubscribed(authorId: string): Promise { } export async function postSubscribe(authorId: string) { - await fetch(buildPath(`auth/subscriptions/${authorId}`), { + await fetchErrorHandle(await fetch(buildPath(`auth/subscriptions/${authorId}`), { method: "POST", ...buildAuthHeaders() - }); + })); } export async function deleteUnsubscribe(authorId: string) { - await fetch(buildPath(`auth/subscriptions/${authorId}`), { + await fetchErrorHandle(await fetch(buildPath(`auth/subscriptions/${authorId}`), { method: 'DELETE', ...buildAuthHeaders() - }); + })); } export async function getHistory(page: number = 1): Promise { - const resp = await fetch(buildPath(`auth/history?page=${page}`), buildAuthHeaders()); + const resp = await fetchErrorHandle(await fetch(buildPath(`auth/history?page=${page}`), buildAuthHeaders())); return await resp.json(); } @@ -146,17 +159,17 @@ export async function deleteHistory(videoId: string | undefined = undefined) { url += `/${videoId}`; } - await fetch(buildPath(url), { + await fetchErrorHandle(await fetch(buildPath(url), { method: 'DELETE', ...buildAuthHeaders() - }); + })); } export async function postHistory(videoId: string) { - await fetch(buildPath(`auth/history/${videoId}`), { + await fetchErrorHandle(await fetch(buildPath(`auth/history/${videoId}`), { method: 'POST', ...buildAuthHeaders() - }); + })); } export async function getPlaylist(playlistId: string, page: number = 1): Promise { @@ -167,44 +180,45 @@ export async function getPlaylist(playlistId: string, page: number = 1): Promise } else { resp = await fetch(buildPath(`playlists/${playlistId}?page=${page}`)); } + await fetchErrorHandle(resp); return await resp.json(); } export async function getPersonalPlaylists(): Promise { - const resp = await fetch(buildPath('auth/playlists'), buildAuthHeaders()); + const resp = await fetchErrorHandle(await fetch(buildPath('auth/playlists'), buildAuthHeaders())); return await resp.json(); } export async function deletePersonalPlaylist(playlistId: string) { - await fetch(buildPath(`auth/playlists/${playlistId}`), { + await fetchErrorHandle(await fetch(buildPath(`auth/playlists/${playlistId}`), { method: 'DELETE', ...buildAuthHeaders() - }); + })); } export async function postPersonalPlaylist(title: string, privacy: 'public' | 'private' | 'unlisted') { let headers: Record> = buildAuthHeaders(); headers['headers']['Content-type'] = 'application/json'; - await fetch(buildPath('auth/playlists'), { + await fetchErrorHandle(await fetch(buildPath('auth/playlists'), { method: 'POST', body: JSON.stringify({ title: title, privacy: privacy }), ...headers - }); + })); } export async function addPlaylistVideo(playlistId: string, videoId: string) { let headers: Record> = buildAuthHeaders(); headers['headers']['Content-type'] = 'application/json'; - await fetch(buildPath(`auth/playlists/${playlistId}/videos`), { + await fetchErrorHandle(await fetch(buildPath(`auth/playlists/${playlistId}/videos`), { method: 'POST', body: JSON.stringify({ videoId: videoId }), ...headers - }); + })); } \ No newline at end of file diff --git a/materialious/src/routes/+layout.svelte b/materialious/src/routes/+layout.svelte index 28f6df41..cc03ef81 100644 --- a/materialious/src/routes/+layout.svelte +++ b/materialious/src/routes/+layout.svelte @@ -186,11 +186,7 @@ } if (isLoggedIn) { - try { - loadNotifications(); - } catch { - auth.set(null); - } + loadNotifications().catch(() => auth.set(null)); } }); diff --git a/materialious/src/routes/channel/[slug]/+page.ts b/materialious/src/routes/channel/[slug]/+page.ts index 28228442..276a818e 100644 --- a/materialious/src/routes/channel/[slug]/+page.ts +++ b/materialious/src/routes/channel/[slug]/+page.ts @@ -1,7 +1,16 @@ import { getChannel } from '$lib/Api/index.js'; +import { error } from '@sveltejs/kit'; export async function load({ params }) { + let channel; + + try { + channel = await getChannel(params.slug); + } catch (errorMessage: any) { + error(500, errorMessage); + } + return { - channel: await getChannel(params.slug) + channel: channel }; } \ No newline at end of file diff --git a/materialious/src/routes/history/+page.svelte b/materialious/src/routes/history/+page.svelte index 387763df..ba4328cf 100644 --- a/materialious/src/routes/history/+page.svelte +++ b/materialious/src/routes/history/+page.svelte @@ -2,6 +2,7 @@ import { deleteHistory, getHistory, getVideo } from '$lib/Api'; import type { VideoPlay } from '$lib/Api/model'; import VideoList from '$lib/VideoList.svelte'; + import { error } from '@sveltejs/kit'; import { onDestroy, onMount } from 'svelte'; import { activePage } from '../../store'; @@ -13,14 +14,18 @@ let currentPage = 1; async function loadPageHistory() { - const videoIds = await getHistory(currentPage); - let promises = []; - for (const videoId of videoIds) { - promises.push(getVideo(videoId)); - } + try { + const videoIds = await getHistory(currentPage); + let promises = []; + for (const videoId of videoIds) { + promises.push(getVideo(videoId)); + } - const loadedHistory = await Promise.all(promises); - history = [...history, ...loadedHistory]; + const loadedHistory = await Promise.all(promises); + history = [...history, ...loadedHistory]; + } catch (errorMessage: any) { + error(500, errorMessage); + } } async function handleScroll() { diff --git a/materialious/src/routes/playlist/[slug]/+page.ts b/materialious/src/routes/playlist/[slug]/+page.ts index 64fec2ff..939fe023 100644 --- a/materialious/src/routes/playlist/[slug]/+page.ts +++ b/materialious/src/routes/playlist/[slug]/+page.ts @@ -1,7 +1,15 @@ import { getPlaylist } from '$lib/Api/index.js'; +import { error } from '@sveltejs/kit'; export async function load({ params }) { + let playlist; + + try { + playlist = await getPlaylist(params.slug); + } catch (errorMessage: any) { + error(500, errorMessage); + } return { - playlist: await getPlaylist(params.slug) + playlist: playlist }; } \ No newline at end of file diff --git a/materialious/src/routes/playlists/+page.ts b/materialious/src/routes/playlists/+page.ts index 27d45fd1..2efe5cc1 100644 --- a/materialious/src/routes/playlists/+page.ts +++ b/materialious/src/routes/playlists/+page.ts @@ -1,7 +1,14 @@ import { getPersonalPlaylists } from "$lib/Api"; +import { error } from "@sveltejs/kit"; export async function load() { + let playlists; + try { + playlists = await getPersonalPlaylists(); + } catch (errorMessage: any) { + error(500, errorMessage); + } return { - playlists: await getPersonalPlaylists() + playlists: playlists }; } \ No newline at end of file diff --git a/materialious/src/routes/search/[slug]/+page.ts b/materialious/src/routes/search/[slug]/+page.ts index b800dedb..1b96ce67 100644 --- a/materialious/src/routes/search/[slug]/+page.ts +++ b/materialious/src/routes/search/[slug]/+page.ts @@ -1,4 +1,5 @@ import { getSearch } from '$lib/Api/index'; +import { error } from '@sveltejs/kit'; export async function load({ params, url }) { let type: "playlist" | "all" | "video" | "channel"; @@ -9,8 +10,17 @@ export async function load({ params, url }) { } else { type = 'all'; } + + let search; + + try { + search = await getSearch(params.slug, { type: type }); + } catch (errorMessage: any) { + error(500, errorMessage); + } + return { - search: await getSearch(params.slug, { type: type }), + search: search, slug: params.slug, searchType: type }; diff --git a/materialious/src/routes/subscriptions/+page.ts b/materialious/src/routes/subscriptions/+page.ts index eebb7dcc..1102ee7b 100644 --- a/materialious/src/routes/subscriptions/+page.ts +++ b/materialious/src/routes/subscriptions/+page.ts @@ -2,13 +2,14 @@ import { getFeed } from '$lib/Api/index.js'; import { error } from '@sveltejs/kit'; export async function load({ params }) { - const feed = await getFeed(100, 1); - - if ('errorBacktrace' in feed) ( - error(500, (feed as { errorBacktrace: string; }).errorBacktrace) - ); + let feed; + try { + feed = await getFeed(100, 1); + } catch (errorMessage: any) { + error(500, errorMessage); + } return { - feed: await getFeed(100, 1) + feed: feed }; } \ No newline at end of file diff --git a/materialious/src/routes/trending/+page.ts b/materialious/src/routes/trending/+page.ts index 64de06e2..a75195f2 100644 --- a/materialious/src/routes/trending/+page.ts +++ b/materialious/src/routes/trending/+page.ts @@ -1,12 +1,14 @@ import { getTrending } from '$lib/Api/index.js'; +import type { Video } from '$lib/Api/model'; import { error } from '@sveltejs/kit'; -export async function load({ params }) { - const trending = await getTrending(); - - if ('errorBacktrace' in trending) ( - error(500, (trending as { errorBacktrace: string; }).errorBacktrace) - ); +export async function load() { + let trending: Video[]; + try { + trending = await getTrending(); + } catch (errorMessage: any) { + error(500, errorMessage); + } return { trending: trending }; } \ No newline at end of file diff --git a/materialious/src/routes/watch/[slug]/+page.svelte b/materialious/src/routes/watch/[slug]/+page.svelte index 2373a2c9..c804fda3 100644 --- a/materialious/src/routes/watch/[slug]/+page.svelte +++ b/materialious/src/routes/watch/[slug]/+page.svelte @@ -190,6 +190,12 @@ {/each} + {:else} + {/if} diff --git a/materialious/src/routes/watch/[slug]/+page.ts b/materialious/src/routes/watch/[slug]/+page.ts index 84b12d79..0e24d9bf 100644 --- a/materialious/src/routes/watch/[slug]/+page.ts +++ b/materialious/src/routes/watch/[slug]/+page.ts @@ -7,11 +7,11 @@ import { auth, playerProxyVideos, returnYtDislikes } from '../../../store'; export async function load({ params, url }) { let video; - video = await getVideo(params.slug, get(playerProxyVideos)); - - if ('errorBacktrace' in video) ( - error(500, (video as { errorBacktrace: string; }).errorBacktrace) - ); + try { + video = await getVideo(params.slug, get(playerProxyVideos)); + } catch (errorMessage: any) { + error(500, errorMessage); + } let personalPlaylists: PlaylistPage[] | null; From 2abbc0cbbdf0ae90046fd8e326a4b0da1af4fadf Mon Sep 17 00:00:00 2001 From: WardPearce Date: Tue, 2 Apr 2024 09:46:01 +1300 Subject: [PATCH 2/2] Fixed white flashbang --- materialious/src/app.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/materialious/src/app.html b/materialious/src/app.html index e1839043..47019a56 100644 --- a/materialious/src/app.html +++ b/materialious/src/app.html @@ -12,7 +12,7 @@ %sveltekit.head% - +
%sveltekit.body%