v0.5.84: matches origin filter, mobile gate, refresh reliability.

Ship Web refresh cache/lock, mobile demand gate, matches 职业/国服 filter, and related site updates through 0.5.84.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
voson
2026-07-29 18:31:55 +08:00
co-authored by Cursor
parent 7681fdb069
commit b01552ee6e
50 changed files with 3406 additions and 487 deletions
+32
View File
@@ -7,6 +7,8 @@ timeout, and retry conventions live in exactly one place.
from __future__ import annotations
import json
import os
import tempfile
import time
import urllib.error
import urllib.request
@@ -22,6 +24,36 @@ HEROES_URL = "https://www.dota2.com/datafeed/herolist?language={lang}"
ITEMLIST_URL = "https://www.dota2.com/datafeed/itemlist?language={lang}"
def write_json_atomic(
path: Path,
payload,
*,
indent: int | None = 2,
separators: tuple[str, str] | None = None,
) -> None:
"""Atomically replace a UTF-8 JSON file after flushing it to disk."""
path.parent.mkdir(parents=True, exist_ok=True)
text = json.dumps(
payload,
ensure_ascii=False,
indent=indent,
separators=separators,
)
if indent is not None:
text += "\n"
fd, tmp_name = tempfile.mkstemp(prefix=f".{path.name}.", suffix=".tmp", dir=path.parent)
tmp = Path(tmp_name)
try:
with os.fdopen(fd, "w", encoding="utf-8", newline="\n") as f:
f.write(text)
f.flush()
os.fsync(f.fileno())
os.replace(tmp, path)
except BaseException:
tmp.unlink(missing_ok=True)
raise
def _http_open(url: str, *, timeout: int, retries: int, backoff: float):
"""urlopen with retries on 429 / 5xx / transient network errors."""
last_err: BaseException | None = None