From 1e788203f28f037ca6c2ffdc9fe667f7cd01fca8 Mon Sep 17 00:00:00 2001 From: Yuri Tatishchev Date: Thu, 5 Feb 2026 20:05:50 -0800 Subject: [PATCH] fix mal querying --- src/lib/types/mal/index.ts | 2 +- .../api/mal/animelist/[username]/+server.ts | 4 +++- src/routes/list/+page.svelte | 18 +++++++++--------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/lib/types/mal/index.ts b/src/lib/types/mal/index.ts index 59ee958..df83da1 100644 --- a/src/lib/types/mal/index.ts +++ b/src/lib/types/mal/index.ts @@ -54,7 +54,7 @@ export const MalAnimeListEntry = z score: z.number().int().min(0).max(10), num_episodes_watched: z.number().int().min(0), is_rewatching: z.boolean(), - updated_at: z.iso.datetime(), + updated_at: z.iso.datetime({ offset: true }), start_date: z.iso.date().optional(), finish_date: z.iso.date().optional(), }) diff --git a/src/routes/api/mal/animelist/[username]/+server.ts b/src/routes/api/mal/animelist/[username]/+server.ts index e2d26a4..e6ea9b0 100644 --- a/src/routes/api/mal/animelist/[username]/+server.ts +++ b/src/routes/api/mal/animelist/[username]/+server.ts @@ -26,7 +26,9 @@ export const GET: RequestHandler = async ({ params, request, fetch, url }) => { `${UPSTREAM_ORIGIN}/users/${encodeURIComponent(username)}/animelist`, ); - upstreamUrl.search = url.search; + const upstreamSearch = new URLSearchParams(url.search); + upstreamSearch.set("fields", "list_status"); + upstreamUrl.search = upstreamSearch.toString(); const ifNoneMatch = pickForwardHeader(request, "if-none-match"); const ifModifiedSince = pickForwardHeader(request, "if-modified-since"); diff --git a/src/routes/list/+page.svelte b/src/routes/list/+page.svelte index 2b1c2ef..2c29db7 100644 --- a/src/routes/list/+page.svelte +++ b/src/routes/list/+page.svelte @@ -14,7 +14,7 @@ } from "$lib/types/mal"; const ListSearchSchema = MalAnimeListQuerySchema.extend({ - mal: z.string(), + mal: z.string().default(""), }).strict(); type PageStatus = "idle" | "loading" | "ready" | "error"; @@ -31,7 +31,7 @@ let isLoadingDb = $state(false); // Keep MAL calls snappy if you later add more query params; for now it's mostly future-proofing. - const debouncedMalUser = new Debounced(() => params.mal, 250); + const debouncedMalUser = new Debounced(() => params.mal ?? "", 1000); type MalListResponse = z.infer; type MalEntry = MalListResponse["data"][number]; @@ -79,8 +79,8 @@ return MalAnimeListResponseSchema.parse(json); } - async function loadAllFor(username: string) { - const u = username.trim(); + async function loadAllFor(username: string | undefined) { + const u = (username ?? "").trim(); if (!u) { malResponse = null; malEntries = []; @@ -109,7 +109,7 @@ const { db } = getClientDb(); const malIds = (malResponse?.data ?? []).map((e) => e.node.id); - songRows = await querySongsForMalAnimeIds(db, malIds); + songRows = await getSongsForMalAnimeIds(db, malIds); } finally { isLoadingDb = false; } @@ -178,7 +178,7 @@ id="mal-user" class="rounded border px-3 py-2 text-sm" placeholder="e.g. CaZzzer" - value={params.mal} + value={params.mal ?? ""} oninput={(e) => (params.mal = (e.currentTarget as HTMLInputElement).value)} autocomplete="off" @@ -186,7 +186,7 @@ />
- {#if !params.mal.trim()} + {#if !(params.mal ?? "").trim()} Waiting for username… {:else} {#if isLoadingMal} @@ -217,13 +217,13 @@ {/if}
- {#if params.mal.trim() && !isLoadingMal && malEntries.length === 0} + {#if (params.mal ?? "").trim() && !isLoadingMal && malEntries.length === 0}

No anime returned from MAL (did you set a restrictive status/sort?).

{/if} - {#if params.mal.trim() && !isLoadingDb && malEntries.length > 0 && songRows.length === 0} + {#if (params.mal ?? "").trim() && !isLoadingDb && malEntries.length > 0 && songRows.length === 0}

No songs matched in the local database. This likely means none of the MAL anime IDs exist in the snapshot DB.