From 5e9433563bacb625421c06da122f863fae3af785 Mon Sep 17 00:00:00 2001 From: pleb Date: Tue, 4 Nov 2025 13:32:39 -0800 Subject: [PATCH] Route beatleader profile requests through ssr --- src/lib/components/PlayerCompareForm.svelte | 18 +++---------- src/lib/utils/plebsaber-utils.ts | 27 +++++++++++++++++++ .../tools/player-playlist-gaps/+page.svelte | 15 +++-------- src/routes/tools/stats/+page.server.ts | 27 +++---------------- 4 files changed, 37 insertions(+), 50 deletions(-) diff --git a/src/lib/components/PlayerCompareForm.svelte b/src/lib/components/PlayerCompareForm.svelte index 498eda4..7788af9 100644 --- a/src/lib/components/PlayerCompareForm.svelte +++ b/src/lib/components/PlayerCompareForm.svelte @@ -2,7 +2,7 @@ import { onMount } from 'svelte'; import { browser } from '$app/environment'; import PlayerCard from '$lib/components/PlayerCard.svelte'; - import type { BeatLeaderPlayerProfile } from '$lib/utils/plebsaber-utils'; + import { fetchBeatLeaderPlayerProfile, type BeatLeaderPlayerProfile } from '$lib/utils/plebsaber-utils'; export let playerA = ''; export let playerB = ''; @@ -69,23 +69,13 @@ history.replaceState(null, '', url); } - async function fetchPlayerProfile(playerId: string): Promise { - try { - const res = await fetch(`https://api.beatleader.xyz/player/${encodeURIComponent(playerId)}`); - if (!res.ok) return null; - return (await res.json()) as BeatLeaderPlayerProfile; - } catch { - return null; - } - } - async function loadDefaultPlayerCards(a: string, b: string): Promise { playerAProfile = null; playerBProfile = null; if (!a || !b) return; const [pa, pb] = await Promise.all([ - fetchPlayerProfile(a), - fetchPlayerProfile(b) + fetchBeatLeaderPlayerProfile(a), + fetchBeatLeaderPlayerProfile(b) ]); playerAProfile = pa; playerBProfile = pb; @@ -110,7 +100,7 @@ } try { - const profile = await fetchPlayerProfile(trimmed); + const profile = await fetchBeatLeaderPlayerProfile(trimmed); // Only update if this is still the current player ID const currentId = player === 'A' ? playerA.trim() : playerB.trim(); if (currentId === trimmed) { diff --git a/src/lib/utils/plebsaber-utils.ts b/src/lib/utils/plebsaber-utils.ts index 90b3892..e27ca86 100644 --- a/src/lib/utils/plebsaber-utils.ts +++ b/src/lib/utils/plebsaber-utils.ts @@ -225,6 +225,33 @@ export async function fetchBeatLeaderStarsByHash( } } +export async function fetchBeatLeaderPlayerProfile( + playerId: string, + fetcher?: typeof fetch, + authMode: 'steam' | 'oauth' | 'session' | 'auto' | 'none' = 'auto' +): Promise { + const trimmed = playerId?.trim?.(); + if (!trimmed) return null; + + const callFetch = (fetcher ?? globalThis.fetch) as typeof fetch | undefined; + if (!callFetch) return null; + + const search = new URLSearchParams(); + if (authMode) { + search.set('auth', authMode); + } + + const url = `/api/beatleader/player/${encodeURIComponent(trimmed)}${search.size ? `?${search.toString()}` : ''}`; + + try { + const res = await callFetch(url); + if (!res.ok) return null; + return (await res.json()) as BeatLeaderPlayerProfile; + } catch { + return null; + } +} + /** * Load metadata for a list of items with unique hashes * Only loads metadata that isn't already in the cache diff --git a/src/routes/tools/player-playlist-gaps/+page.svelte b/src/routes/tools/player-playlist-gaps/+page.svelte index 4b8dcf2..e0d64a9 100644 --- a/src/routes/tools/player-playlist-gaps/+page.svelte +++ b/src/routes/tools/player-playlist-gaps/+page.svelte @@ -8,6 +8,7 @@ type BeatLeaderPlayerProfile, fetchAllPlayerScores, fetchBeatSaverMeta, + fetchBeatLeaderPlayerProfile, type MapMeta } from '$lib/utils/plebsaber-utils'; @@ -154,7 +155,7 @@ loadingPreview = true; try { - const profile = await fetchPlayerProfile(id); + const profile = await fetchBeatLeaderPlayerProfile(id); // Only update if this is still the current player ID if (playerId.trim() === id) { previewPlayerProfile = profile; @@ -330,16 +331,6 @@ URL.revokeObjectURL(url); } - async function fetchPlayerProfile(id: string): Promise { - try { - const res = await fetch(`https://api.beatleader.xyz/player/${encodeURIComponent(id)}`); - if (!res.ok) return null; - return (await res.json()) as BeatLeaderPlayerProfile; - } catch { - return null; - } - } - async function onAnalyze(ev: SubmitEvent) { ev.preventDefault(); errorMsg = null; @@ -359,7 +350,7 @@ try { const [scores, profile] = await Promise.all([ fetchAllPlayerScores(playerId.trim(), 150), - fetchPlayerProfile(playerId.trim()) + fetchBeatLeaderPlayerProfile(playerId.trim()) ]); analyzedPlayerProfile = profile; hasAnalyzed = true; diff --git a/src/routes/tools/stats/+page.server.ts b/src/routes/tools/stats/+page.server.ts index 3ee8cbb..8d6d088 100644 --- a/src/routes/tools/stats/+page.server.ts +++ b/src/routes/tools/stats/+page.server.ts @@ -1,6 +1,6 @@ import { error, redirect } from '@sveltejs/kit'; import { getAllSessions, getSession } from '$lib/server/sessionStore'; -import { PLEB_BEATLEADER_ID } from '$lib/utils/plebsaber-utils'; +import { PLEB_BEATLEADER_ID, fetchBeatLeaderPlayerProfile } from '$lib/utils/plebsaber-utils'; import type { PageServerLoad } from './$types'; type StatsUser = { @@ -16,28 +16,7 @@ type StatsUser = { lastSeenIso: string; }; -type BeatLeaderPlayer = { - id: string; - name: string; - avatar?: string; - country?: string; - rank?: number; - techPp?: number; - accPp?: number; - passPp?: number; -}; - -async function fetchBeatLeaderProfile(playerId: string): Promise { - try { - const response = await fetch(`https://api.beatleader.xyz/player/${playerId}`); - if (!response.ok) return null; - return (await response.json()) as BeatLeaderPlayer; - } catch { - return null; - } -} - -export const load: PageServerLoad = async ({ cookies }) => { +export const load: PageServerLoad = async ({ cookies, fetch }) => { const currentSession = getSession(cookies); if (!currentSession) { throw redirect(302, '/auth/beatleader/login?redirect_uri=%2Ftools%2Fstats'); @@ -59,7 +38,7 @@ export const load: PageServerLoad = async ({ cookies }) => { // Fetch all player profiles in parallel const userPromises = Array.from(aggregated.values()).map(async ({ session }) => { - const profile = await fetchBeatLeaderProfile(session.beatleaderId); + const profile = await fetchBeatLeaderPlayerProfile(session.beatleaderId, fetch); return { beatleaderId: session.beatleaderId, name: profile?.name ?? session.name,