diff options
| author | n0tori <188390306+n0tori@users.noreply.github.com> | 2026-06-17 21:13:19 +0100 |
|---|---|---|
| committer | n0tori <188390306+n0tori@users.noreply.github.com> | 2026-06-17 21:13:19 +0100 |
| commit | 52fdbc7682b53d9876e9550ace399b7280450a23 (patch) | |
| tree | ce9b557ef5c541839ea4f80f1025bbc6423f7dd8 /dailypuzzle.py | |
| parent | bc16fab83ac9ba897a469d7e8d24c7f6bc58658f (diff) | |
files
Diffstat (limited to 'dailypuzzle.py')
| -rw-r--r-- | dailypuzzle.py | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/dailypuzzle.py b/dailypuzzle.py new file mode 100644 index 0000000..d4f884e --- /dev/null +++ b/dailypuzzle.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +import chess +import chess.pgn +import io +import json +import os +import time +import urllib.request + +OUT = "/var/www/aryanmustafa/api/dailypuzzle" +INTERVAL = 3600 # check every hour; Lichess updates once per day + +os.makedirs(os.path.dirname(OUT), exist_ok=True) + +while True: + try: + req = urllib.request.Request( + "https://lichess.org/api/puzzle/daily", + headers={"Accept": "application/json"}, + ) + with urllib.request.urlopen(req, timeout=10) as r: + raw = json.loads(r.read()) + + puzzle = raw["puzzle"] + game = raw["game"] + + # Lichess returns the full game PGN; the puzzle starts at initialPly. + # Replay up to that ply with python-chess to get the exact FEN. + pgn_text = game["pgn"] + initial_ply = puzzle["initialPly"] + + parsed = chess.pgn.read_game(io.StringIO(pgn_text)) + board = parsed.board() + for i, move in enumerate(parsed.mainline_moves()): + board.push(move) + if i >= initial_ply: + break + + result = { + "id": puzzle["id"], + "fen": board.fen(), + "side": "white" if board.turn == chess.WHITE else "black", + "solution": puzzle["solution"], # UCI list e.g. ["e2e4","d7d5"] + "rating": puzzle.get("rating"), + "themes": puzzle.get("themes", []), + "url": f"https://lichess.org/training/{puzzle['id']}", + } + + tmp = OUT + ".tmp" + with open(tmp, "w") as f: + json.dump(result, f) + os.replace(tmp, OUT) # atomic write + + print(f"updated: puzzle {result['id']}", flush=True) + + except Exception as e: + print(f"error: {e}", flush=True) + + time.sleep(INTERVAL) |
