Make roster refresh rebuild from SchaleDB base and fail-safe

This commit is contained in:
esef committed 2026-09-15 15:30:16 +03:00
1 parent c8e3ab57cc
commit 45f4dfd653
2 files changed
+55 -22

No files matched your search

+33 -10
View File
@@ -1,28 +1,51 @@
"""Refresh the bundled Blue Archive roster from the live ennead.cc API.
"""Rebuild the bundled Blue Archive roster from upstream sources.
Loads the current ba_students.json, merges any characters that have been
released since the last run, and atomically writes the result back. Run weekly
via the discordbot-refresh systemd timer so fresh clones stay current without
depending on the live API at startup.
Downloads the latest SchaleDB export (full fields including portrait data),
then merges the live ennead.cc character feed for anything SchaleDB doesn't
cover (variants, welfare, collabs). Writes the result atomically.
Fails WITHOUT writing if any required upstream fetch fails, so a transient
network error can never shrink the existing roster.
Run weekly via the discordbot-refresh systemd timer.
"""
import asyncio
import json
from pathlib import Path
from blue_archive.data import db, fetch_banners
import aiohttp
from blue_archive.constants import CHARACTER_API
from blue_archive.data import StudentDB, fetch_banners
SCHALEDB_URL = "https://raw.githubusercontent.com/SchaleDB/SchaleDB/main/data/en/students.min.json"
OUT = Path(__file__).with_name("ba_students.json")
async def fetch_json(session: aiohttp.ClientSession, url: str, timeout: int = 30) -> list[dict]:
async with session.get(url, timeout=aiohttp.ClientTimeout(total=timeout)) as resp:
resp.raise_for_status()
return json.loads(await resp.text())
async def main() -> None:
db.load()
banners = await fetch_banners()
added = await db.merge_ennead(banners)
async with aiohttp.ClientSession() as session:
base = await fetch_json(session, SCHALEDB_URL)
chars = await fetch_json(session, CHARACTER_API)
banners = await fetch_banners(session)
if not chars:
raise RuntimeError("ennead character API returned an empty list")
db = StudentDB()
db.load_data(base)
added = db.merge_chars(chars, banners)
tmp = OUT.with_suffix(".json.tmp")
tmp.write_text(json.dumps(db.students, ensure_ascii=False), encoding="utf-8")
tmp.replace(OUT) # atomic swap so a reader never sees a partial file
print(f"refreshed {OUT.name}: {len(db.students)} students (+{added} new)")
print(f"refreshed {OUT.name}: {len(db.students)} students "
f"(SchaleDB {len(base)} + {added} ennead)")
if __name__ == "__main__":