From 4bd6e71e8cd3c88565cb46ddd6f421b3db02496c Mon Sep 17 00:00:00 2001 From: mkelvers Date: Fri, 15 May 2026 17:22:56 +0200 Subject: [PATCH] fix: handle empty random anime response and improve surprise-me UX --- integrations/jikan/client.go | 7 ++-- integrations/jikan/seasons.go | 3 ++ internal/anime/handler/handler.go | 4 +++ templates/discover.gohtml | 58 +++++++++++++++++++------------ 4 files changed, 44 insertions(+), 28 deletions(-) diff --git a/integrations/jikan/client.go b/integrations/jikan/client.go index 20915e7..9050c46 100644 --- a/integrations/jikan/client.go +++ b/integrations/jikan/client.go @@ -339,12 +339,9 @@ func (c *Client) fetchWithRetry(ctx context.Context, urlStr string, out any) err continue } - err = json.NewDecoder(resp.Body).Decode(out) + // Best-effort decode (often useful for debugging), but still treat non-200 as error. + _ = json.NewDecoder(resp.Body).Decode(out) _ = resp.Body.Close() - if err == nil { - return nil - } - return apiErr } diff --git a/integrations/jikan/seasons.go b/integrations/jikan/seasons.go index b86b6b6..eefbb23 100644 --- a/integrations/jikan/seasons.go +++ b/integrations/jikan/seasons.go @@ -63,6 +63,9 @@ func (c *Client) GetRandomAnime(ctx context.Context) (Anime, error) { if err != nil { return Anime{}, err } + if result.Data.MalID == 0 { + return Anime{}, fmt.Errorf("jikan: empty response for random/anime") + } return result.Data, nil } diff --git a/internal/anime/handler/handler.go b/internal/anime/handler/handler.go index d97e7a5..28f9522 100644 --- a/internal/anime/handler/handler.go +++ b/internal/anime/handler/handler.go @@ -383,6 +383,10 @@ func (h *AnimeHandler) HandleRandomAnime(c *gin.Context) { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch random anime"}) return } + if anime.MalID == 0 { + c.JSON(http.StatusBadGateway, gin.H{"error": "Random anime unavailable"}) + return + } user, _ := c.Get("User") inWatchlist := false diff --git a/templates/discover.gohtml b/templates/discover.gohtml index 3ba04fe..eb6ed72 100644 --- a/templates/discover.gohtml +++ b/templates/discover.gohtml @@ -3,31 +3,43 @@ + async function handleSurpriseMe() { + if (isFetchingRandom) return; + isFetchingRandom = true; + const btn = document.getElementById('surprise-btn'); + const spinner = document.getElementById('surprise-spinner'); + const text = document.getElementById('surprise-text'); + const icon = document.getElementById('surprise-icon'); + btn?.setAttribute('disabled', 'true'); + spinner?.classList.remove('hidden'); + icon?.classList.add('hidden'); + if (text) text.textContent = 'Picking…'; + try { + const res = await fetch(`/api/jikan/random/anime?t=${Date.now()}`, { + cache: 'no-store' + }); + if (!res.ok) throw new Error('Failed to fetch random anime'); + const json = await res.json(); + if (json.data && typeof json.data.mal_id === 'number' && json.data.mal_id > 0) { + window.location.href = `/anime/${json.data.mal_id}`; + return; + } + throw new Error('Random anime missing mal_id'); + } catch (error) { + console.error(error); + alert('Could not pick a random anime right now. Please try again.'); + } finally { + isFetchingRandom = false; + btn?.removeAttribute('disabled'); + spinner?.classList.add('hidden'); + icon?.classList.remove('hidden'); + if (text) text.textContent = 'Surprise Me'; + } + } +
-
+