fix: handle empty random anime response and improve surprise-me UX
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -3,31 +3,43 @@
|
||||
<script>
|
||||
let isFetchingRandom = false;
|
||||
|
||||
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');
|
||||
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 && json.data.mal_id) {
|
||||
window.location.href = `/anime/${json.data.mal_id}`;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
isFetchingRandom = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
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';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col gap-12 pb-12">
|
||||
<section class="relative flex flex-col items-center justify-center overflow-hidden rounded-2xl bg-background-surface px-6 py-24 text-center ring-1 ring-border">
|
||||
<section class="relative flex flex-col items-center justify-center overflow-hidden bg-background-surface px-6 py-24 text-center ring-1 ring-border">
|
||||
<div class="from-accent/10 absolute inset-0 bg-linear-to-b to-transparent opacity-50"></div>
|
||||
<div class="relative z-10 flex max-w-2xl flex-col items-center gap-6">
|
||||
<h1 class="text-4xl font-normal tracking-tight text-foreground sm:text-5xl">
|
||||
|
||||
Reference in New Issue
Block a user