fixing the definition api issue
CI / regression (push) Successful in 2m45s
CI / regression (pull_request) Successful in 2m3s

This commit is contained in:
Zakaria
2026-08-24 00:59:48 -04:00
parent 291f4415e0
commit e0a29438be
4 changed files with 124 additions and 27 deletions
Vendored
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -10,7 +10,7 @@
<script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2"></script> <script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2"></script>
<script src="word-data.js?v=5" defer></script> <script src="word-data.js?v=5" defer></script>
<script src="supabase-config.js?v=1" defer></script> <script src="supabase-config.js?v=1" defer></script>
<script src="script.js?v=10" defer></script> <script src="script.js?v=11" defer></script>
</head> </head>
<body class="intro-active dark-theme"> <body class="intro-active dark-theme">
<section class="intro-overlay" id="intro-overlay" aria-label="Animated Wordle intro" role="dialog" aria-modal="true"> <section class="intro-overlay" id="intro-overlay" aria-label="Animated Wordle intro" role="dialog" aria-modal="true">
+1 -1
View File
@@ -10,7 +10,7 @@
<script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2"></script> <script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2"></script>
<script src="word-data.js?v=5" defer></script> <script src="word-data.js?v=5" defer></script>
<script src="supabase-config.js?v=1" defer></script> <script src="supabase-config.js?v=1" defer></script>
<script src="script.js?v=10" defer></script> <script src="script.js?v=11" defer></script>
</head> </head>
<body class="intro-active dark-theme"> <body class="intro-active dark-theme">
<section class="intro-overlay" id="intro-overlay" aria-label="Animated Wordle intro" role="dialog" aria-modal="true"> <section class="intro-overlay" id="intro-overlay" aria-label="Animated Wordle intro" role="dialog" aria-modal="true">
+122 -25
View File
@@ -27,6 +27,9 @@ const FLIP_ANIMATION_DURATION = 500
const DANCE_ANIMATION_DURATION = 500 const DANCE_ANIMATION_DURATION = 500
const STATS_KEY = "fancy-wordle-stats-v2" const STATS_KEY = "fancy-wordle-stats-v2"
const LOCAL_ROUND_KEY = "fancy-wordle-hourly-round-v1" const LOCAL_ROUND_KEY = "fancy-wordle-hourly-round-v1"
const DEFINITION_CACHE_KEY = "fancy-wordle-definitions-v1"
const DEFINITION_CACHE_LIMIT = 200
const DEFINITION_RETRY_DELAY_MS = 1500
const PLAY_INTERVAL_MS = 60 * 60 * 1000 const PLAY_INTERVAL_MS = 60 * 60 * 1000
const GUESS_TIMEOUT_MS = 10000 const GUESS_TIMEOUT_MS = 10000
const INTRO_SEEN_KEY = "fancy-wordle-intro-seen-v1" const INTRO_SEEN_KEY = "fancy-wordle-intro-seen-v1"
@@ -1367,33 +1370,127 @@ function playCelebrationSound() {
}) })
} }
async function loadWordDefinition(word, isWin = true) { function readDefinitionCache() {
try { try {
const response = await fetch(`https://api.dictionaryapi.dev/api/v2/entries/en/${word}`) const parsed = JSON.parse(localStorage.getItem(DEFINITION_CACHE_KEY))
if (!response.ok) throw new Error(`API request failed: ${response.status}`) return parsed && typeof parsed === "object" ? parsed : {}
} catch {
const data = await response.json() return {}
const firstMeaning = data[0]?.meanings?.[0]
const definition = firstMeaning?.definitions?.[0]?.definition
const partOfSpeech = firstMeaning?.partOfSpeech
const example = firstMeaning?.definitions?.[0]?.example
if (!definition) throw new Error("No definition found")
lastDefinition = {
title: `${word.toUpperCase()} ${partOfSpeech ? `(${partOfSpeech})` : ""}`,
body: definition,
example,
isWin
}
} catch (error) {
console.info("Definition lookup unavailable:", error)
lastDefinition = {
title: word.toUpperCase(),
body: "Definition not available at the moment.",
isWin
}
} }
}
function saveDefinitionToCache(word, entry) {
try {
const cache = readDefinitionCache()
cache[word.toLowerCase()] = { ...entry, cachedAt: Date.now() }
const trimmed = Object.entries(cache)
.sort((a, b) => (b[1].cachedAt || 0) - (a[1].cachedAt || 0))
.slice(0, DEFINITION_CACHE_LIMIT)
localStorage.setItem(DEFINITION_CACHE_KEY, JSON.stringify(Object.fromEntries(trimmed)))
} catch {
}
}
function stripDefinitionHtml(value) {
return String(value ?? "")
.replace(/<[^>]*>/g, "")
.replaceAll("&nbsp;", " ")
.replace(/\s+/g, " ")
.trim()
}
async function fetchDictionaryApiDefinition(word) {
const response = await fetch(`https://api.dictionaryapi.dev/api/v2/entries/en/${encodeURIComponent(word)}`)
if (!response.ok) {
const error = new Error(`API request failed: ${response.status}`)
error.status = response.status
throw error
}
const data = await response.json()
const entry = data.find(item => Array.isArray(item.meanings) && item.meanings.length > 0) || data[0]
const firstMeaning = entry?.meanings?.[0]
const definition = firstMeaning?.definitions?.[0]?.definition
if (!definition) throw new Error("No definition found")
return {
title: `${word.toUpperCase()} ${firstMeaning.partOfSpeech ? `(${firstMeaning.partOfSpeech})` : ""}`,
body: definition,
example: firstMeaning.definitions?.[0]?.example || undefined
}
}
async function fetchWiktionaryDefinition(word) {
const response = await fetch(`https://en.wiktionary.org/api/rest_v1/page/definition/${encodeURIComponent(word)}`)
if (!response.ok) {
const error = new Error(`Wiktionary request failed: ${response.status}`)
error.status = response.status
throw error
}
const data = await response.json()
const englishEntries = Array.isArray(data?.en) ? data.en : []
const entry = englishEntries.find(item => Array.isArray(item.definitions) && item.definitions.length > 0)
const definitionBlock = entry?.definitions.find(item => stripDefinitionHtml(item.definition))
const definition = stripDefinitionHtml(definitionBlock?.definition)
if (!definition) throw new Error("No definition found")
const rawExample = definitionBlock.parsedExamples?.[0]?.example ?? definitionBlock.examples?.[0]
return {
title: `${word.toUpperCase()} ${entry.partOfSpeech ? `(${String(entry.partOfSpeech).toLowerCase()})` : ""}`,
body: definition,
example: stripDefinitionHtml(rawExample) || undefined
}
}
function waitForDuration(duration) {
return new Promise(resolve => setTimeout(resolve, duration))
}
async function loadWordDefinition(word, isWin = true) {
lastDefinition = null
renderStatsDefinition()
renderLeaderboardResult()
let definitionEntry = null
const cached = readDefinitionCache()[word.toLowerCase()]
if (cached?.body) {
definitionEntry = { ...cached }
} else {
try {
definitionEntry = await fetchDictionaryApiDefinition(word)
} catch (error) {
console.info("Primary definition lookup failed:", error)
if (error.status !== 404) {
await waitForDuration(DEFINITION_RETRY_DELAY_MS)
try {
definitionEntry = await fetchDictionaryApiDefinition(word)
} catch (retryError) {
console.info("Primary definition retry failed:", retryError)
}
}
}
if (!definitionEntry) {
try {
definitionEntry = await fetchWiktionaryDefinition(word)
} catch (error) {
console.info("Fallback definition lookup failed:", error)
}
}
if (definitionEntry) saveDefinitionToCache(word, definitionEntry)
}
lastDefinition = definitionEntry
? { ...definitionEntry, isWin }
: {
title: word.toUpperCase(),
body: "Definition not available at the moment.",
isWin
}
renderStatsDefinition() renderStatsDefinition()
renderLeaderboardResult() renderLeaderboardResult()