Use NYT Wordle API for daily word instead of local list
Fetches today's word from https://www.nytimes.com/svc/wordle/v2/YYYY-MM-DD.json so puzzle numbers and solutions match the official NYT Wordle. Results are cached per day; falls back to the local answer list if the API is unreachable. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
37
wordle.py
37
wordle.py
@@ -11,6 +11,7 @@ from dataclasses import dataclass, field
|
||||
from datetime import date
|
||||
from pathlib import Path
|
||||
|
||||
import aiohttp
|
||||
from nio import AsyncClient
|
||||
|
||||
from utils import send_text, send_html, get_or_create_dm
|
||||
@@ -27,6 +28,9 @@ logger = logging.getLogger("matrixbot")
|
||||
|
||||
_WORDLE_EPOCH = date(2021, 6, 19)
|
||||
|
||||
# Cache: date string -> (word, puzzle_number)
|
||||
_nyt_cache: dict[str, tuple[str, int]] = {}
|
||||
|
||||
# Build lookup sets at import time
|
||||
_ANSWER_LIST = [w.upper() for w in ANSWERS]
|
||||
_VALID_SET = frozenset(w.upper() for w in VALID_GUESSES) | frozenset(_ANSWER_LIST)
|
||||
@@ -152,9 +156,36 @@ def _record_game_result(player_id: str, game: WordleGame):
|
||||
# Core algorithms
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def get_daily_word() -> tuple[str, int]:
|
||||
"""Return (word, puzzle_number) for today's daily puzzle."""
|
||||
async def get_daily_word() -> tuple[str, int]:
|
||||
"""Return (word, puzzle_number) for today's daily puzzle.
|
||||
|
||||
Fetches from the NYT Wordle API. Falls back to the local word list
|
||||
if the request fails.
|
||||
"""
|
||||
today = date.today()
|
||||
date_str = today.strftime("%Y-%m-%d")
|
||||
|
||||
if date_str in _nyt_cache:
|
||||
return _nyt_cache[date_str]
|
||||
|
||||
try:
|
||||
url = f"https://www.nytimes.com/svc/wordle/v2/{date_str}.json"
|
||||
timeout = aiohttp.ClientTimeout(total=5)
|
||||
async with aiohttp.ClientSession(timeout=timeout) as session:
|
||||
async with session.get(url) as resp:
|
||||
if resp.status == 200:
|
||||
data = await resp.json(content_type=None)
|
||||
word = data["solution"].upper()
|
||||
puzzle_number = int(data["id"])
|
||||
_nyt_cache[date_str] = (word, puzzle_number)
|
||||
logger.info("NYT Wordle #%d: %s", puzzle_number, word)
|
||||
return word, puzzle_number
|
||||
else:
|
||||
logger.warning("NYT Wordle API returned %d, falling back to local list", resp.status)
|
||||
except Exception as e:
|
||||
logger.warning("Failed to fetch NYT Wordle word: %s — falling back to local list", e)
|
||||
|
||||
# Fallback: use local answer list
|
||||
puzzle_number = (today - _WORDLE_EPOCH).days
|
||||
word = _ANSWER_LIST[puzzle_number % len(_ANSWER_LIST)]
|
||||
return word, puzzle_number
|
||||
@@ -455,7 +486,7 @@ async def wordle_start_or_status(client: AsyncClient, room_id: str, sender: str,
|
||||
return
|
||||
|
||||
# Check if already completed today's puzzle
|
||||
word, puzzle_number = get_daily_word()
|
||||
word, puzzle_number = await get_daily_word()
|
||||
stats = _get_player_stats(sender)
|
||||
|
||||
if stats["last_daily"] == puzzle_number:
|
||||
|
||||
Reference in New Issue
Block a user