fixing the definition api issue
This commit is contained in:
@@ -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
@@ -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">
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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(" ", " ")
|
||||||
|
.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 data = await response.json()
|
||||||
const firstMeaning = data[0]?.meanings?.[0]
|
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
|
const definition = firstMeaning?.definitions?.[0]?.definition
|
||||||
const partOfSpeech = firstMeaning?.partOfSpeech
|
|
||||||
const example = firstMeaning?.definitions?.[0]?.example
|
|
||||||
|
|
||||||
if (!definition) throw new Error("No definition found")
|
if (!definition) throw new Error("No definition found")
|
||||||
|
|
||||||
lastDefinition = {
|
return {
|
||||||
title: `${word.toUpperCase()} ${partOfSpeech ? `(${partOfSpeech})` : ""}`,
|
title: `${word.toUpperCase()} ${firstMeaning.partOfSpeech ? `(${firstMeaning.partOfSpeech})` : ""}`,
|
||||||
body: definition,
|
body: definition,
|
||||||
example,
|
example: firstMeaning.definitions?.[0]?.example || undefined
|
||||||
isWin
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
} catch (error) {
|
||||||
console.info("Definition lookup unavailable:", error)
|
console.info("Primary definition lookup failed:", error)
|
||||||
lastDefinition = {
|
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(),
|
title: word.toUpperCase(),
|
||||||
body: "Definition not available at the moment.",
|
body: "Definition not available at the moment.",
|
||||||
isWin
|
isWin
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
renderStatsDefinition()
|
renderStatsDefinition()
|
||||||
renderLeaderboardResult()
|
renderLeaderboardResult()
|
||||||
|
|||||||
Reference in New Issue
Block a user