feat(ba): track Blue Archive from its own wiki
New bawiki parser plus the ba-bawiki-events source, giving the game its two live and upcoming events at day precision. It reads the rendered /wiki/Events page, which is the opposite call to the Fandom source next door and for the same kind of reason: bluearchive.wiki is Miraheze, whose robots.txt disallows /w/ and /*?action=, so there the API is the closed route and the page is the surface * is allowed. It serves our own User-Agent a 200, sets no Content-Signal and no Crawl-delay for us. The Fandom wiki was declined earlier as a JP archive yielding nothing live; this is the live source that assessment pointed at. Three page facts shape the parser, each a way to publish a confidently wrong date. The schedule is a JP/Global tabber and the Japanese version runs four to nine months ahead, so only Global is published — the akwiki hazard. The Global tab's nav button carries the id tabber-Global_version-label and precedes both panels, so slicing from the first matching id reads the Japanese schedule while believing it read ours; the first version of this parser did exactly that and published a JP-only event. And three tabs on the page are named Global, the schedule plus Mini-Event and Joint Firing Drill, so the schedule is found by its Name (EN) header rather than by position, with canParse asserting the same lookup — a renamed tab or column fails the run instead of emptying the lane. The page states no time of day and no timezone anywhere, which is why the dates are day precision and why ba gets no resetOffsets. It also settles the five other schedule tables, which do carry a wall clock but name no zone and mostly do not say which server: reading those as UTC would invent the fact that matters most, and rounding to a day would not save it, because a 04:00 local boundary falls either side of UTC midnight depending on the offset assumed and the start's day is part of the event ID. They are left unparsed deliberately. The two-event count is asserted against an independent extraction off the fixture, and both starts corroborate against the per-event infoboxes elsewhere on the page — GL 2026-08-04 and GL 2026-09-01, where the JP reruns those tabs would have given are 2026-04-01 and 2026-05-06. Three comment counts were already stale before this and are corrected to what the tree now holds rather than to what it held yesterday. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
77921e88f5
commit
d843c7cae7
@@ -76,6 +76,7 @@ src/
|
||||
wikigg.ts wiki.gg mp-event templates ✓ built
|
||||
akwiki.ts arknights.wiki.gg mrfz-wtable ✓ built
|
||||
fandom.ts Fandom via the action=parse API ✓ built
|
||||
bawiki.ts bluearchive.wiki JP/Global tabber ✓ built
|
||||
index.ts parser registry ✓ built
|
||||
adapters/
|
||||
types.ts Adapter interface, ParseContext ✓ built
|
||||
|
||||
+9
-5
@@ -10,6 +10,7 @@ import { z } from "zod";
|
||||
|
||||
export const GameId = z.enum([
|
||||
"genshin", "hsr", "zzz", "wuwa", "arknights", "endfield", "nte", "nikki", "p5x", "r1999",
|
||||
"ba",
|
||||
]);
|
||||
|
||||
export const EventType = z.enum([
|
||||
@@ -254,7 +255,7 @@ reader cannot see.
|
||||
| Game | Reset (server local) | Server offset | Reset (UTC) | Copenhagen, summer / winter |
|
||||
|---|---|---|---|---|
|
||||
| Genshin, Star Rail, ZZZ, Wuwa, NTE | 04:00 | region (EU = UTC+1) | 03:00 | 05:00 / 04:00 |
|
||||
| Infinity Nikki, P5X | 04:00 | region (assumed) | 03:00 | 05:00 / 04:00 |
|
||||
| Infinity Nikki, P5X, Blue Archive | 04:00 | region (assumed) | 03:00 | 05:00 / 04:00 |
|
||||
| Arknights, all regions | 04:00 | UTC-7 (one Global server) | 11:00 | 13:00 / 12:00 |
|
||||
| Endfield, Europe | 04:00 | UTC-5 (on the Americas server) | 09:00 | 11:00 / 10:00 |
|
||||
| Endfield, Asia / Americas | 04:00 | regional default | 20:00 / 09:00 | — |
|
||||
@@ -266,10 +267,13 @@ server for every region we model. The offset is read off the source rather than
|
||||
ending event on arknights.wiki.gg carries an exact end of `10:59:59Z`, which is `03:59:59` at UTC-7,
|
||||
one second before a 04:00 reset.
|
||||
|
||||
Infinity Nikki and P5X carry **no `resetOffsets` entry**, so they take the regional default. That is
|
||||
an assumption, not a verified server map — neither source states one. Confirm it against the games
|
||||
before relying on it, and note that adding an override later re-labels the game-day of ticks readers
|
||||
have already logged, which is the change this table warns about below.
|
||||
Infinity Nikki, P5X and Blue Archive carry **no `resetOffsets` entry**, so they take the regional
|
||||
default. That is an assumption, not a verified server map — none of the three sources states one.
|
||||
Blue Archive is the case where the assumption is most likely wrong and still the right entry: the
|
||||
game does run one worldwide server, but `bluearchive.wiki` states no time of day and no timezone
|
||||
anywhere on the page, so there is no offset to read off it. Confirm these against the games before
|
||||
relying on them, and note that adding an override later re-labels the game-day of ticks readers have
|
||||
already logged, which is the change this table warns about below.
|
||||
|
||||
**Reverse: 1999 is the one game that rolls on a different hour**, and it needs its own field rather
|
||||
than a bent offset. It runs a single global server on UTC-5 and resets at **05:00**, so its day rolls
|
||||
|
||||
+2
-2
@@ -121,7 +121,7 @@ Named across the thread, excluding the six already covered:
|
||||
| Arknights | 2 | **`GameId`, hue and `dailyTasks` already exist in `games.ts` with no source registered.** Cheapest possible win. |
|
||||
| Reverse: 1999 | 1 | Named as the one thing between a bookmark and a habit. |
|
||||
| Azur Lane | 1 | OP judged doable |
|
||||
| Blue Archive | 1 | OP judged doable |
|
||||
| Blue Archive | 1 | OP judged doable. **Done** (2026-08-17) — `bluearchive.wiki`, not the Fandom wiki, which is a JP archive yielding nothing live |
|
||||
| Umamusume | 1 | OP judged doable |
|
||||
| Persona 5X | 1 | OP judged doable |
|
||||
| Nikke | 1 | |
|
||||
@@ -305,7 +305,7 @@ diagnosis in each item still holds — what changed is whether it has been acted
|
||||
| P1b cap the long list | **Not done.** No "show all N" expander |
|
||||
| P1b persist `view` | **Not done.** Still `useState` in `App.tsx` |
|
||||
| P1b Calendar → Timeline | **Done.** The tab reads "Timeline" |
|
||||
| P1c more games | **Done, three of them.** Infinity Nikki, Persona 5: The Phantom X, Reverse: 1999 — one commit each. The declined and cleared-but-unbuilt candidates are recorded in `AGENTS.md` § Scraping conduct so they are not re-litigated |
|
||||
| P1c more games | **Done, four of them.** Infinity Nikki, Persona 5: The Phantom X, Reverse: 1999, Blue Archive — one commit each. Of the games named in the thread, Azur Lane and Umamusume are **declined on conduct** rather than pending, and the declined and cleared-but-unbuilt candidates are recorded in `AGENTS.md` § Scraping conduct so they are not re-litigated |
|
||||
| P1c roadmap in the colophon | **Not done** |
|
||||
| P2 colour and screenshot | **Not done** |
|
||||
| P2 custom events | **Done.** PRD F13 first, then the code; `mygame:` / `myevent:` key spaces, in the export |
|
||||
|
||||
@@ -52,6 +52,7 @@ Consequences worth internalising:
|
||||
| `wikigg` | wiki.gg MediaWiki `mp-event` templates | Endfield |
|
||||
| `akwiki` | arknights.wiki.gg's `mrfz-wtable` "Ongoing/upcoming" table | Arknights |
|
||||
| `fandom` | Fandom wikis via the MediaWiki `action=parse` API — `Event \| Time Period \| Version` wikitables | Reverse: 1999 |
|
||||
| `bawiki` | bluearchive.wiki's rendered `/wiki/Events` — a JP/Global tabber over `Name (EN) \| Start date \| End date \| Notes` wikitables | Blue Archive |
|
||||
|
||||
`wikigg` is the better shape by a distance: it emits ISO timestamps with one timer per server
|
||||
region, so its events carry exact precision and real `regionEnds`. Prefer a source like that over a
|
||||
@@ -73,6 +74,21 @@ rather than parse to zero events. Two page facts drive the rest of it:
|
||||
anchor on. Inclusion is therefore decided against `ctx.now`, the one parser here that does so;
|
||||
`akwiki` and `game8` can gate on a heading instead, and should where one exists.
|
||||
|
||||
`bawiki` is the mirror image of `fandom`: same MediaWiki software, opposite conclusion about which
|
||||
surface to read. bluearchive.wiki is Miraheze, whose `robots.txt` disallows `/w/` and `/*?action=`,
|
||||
so the API is closed and the rendered `/wiki/Events` page is what `*` is allowed — and it serves our
|
||||
own `User-Agent` a `200`. Three page facts drive the parser (all three in AGENTS.md § Blue Archive):
|
||||
|
||||
- **JP and Global are separate tabs, months apart**, so only Global is published — the `akwiki`
|
||||
hazard. The Global tab's nav *button* precedes both panels, so slicing from the first matching id
|
||||
reads the Japanese schedule.
|
||||
- **Three tabs are named Global**, the schedule plus Mini-Event and Joint Firing Drill. The schedule
|
||||
is identified by its `Name (EN)` header rather than by position, and `canParse` runs the same
|
||||
lookup so a rename fails the run rather than emptying the lane.
|
||||
- **Nothing on the page states a time of day or a timezone.** The schedule's bare ISO dates are day
|
||||
precision; the five tables that do carry a wall clock name no zone for it and are left unparsed
|
||||
rather than read as UTC.
|
||||
|
||||
`akwiki` shares a host family with `wikigg` and nothing else — arknights.wiki.gg has no `mp-event`
|
||||
cards, so the two are separate modules rather than one parser with a branch. Two things about that
|
||||
page shape are worth knowing before touching it:
|
||||
|
||||
+4
-4
@@ -46,13 +46,13 @@ event, because a missing event sends them to a wiki while a wrong one makes them
|
||||
| Neverness to Everness | `nte` |
|
||||
|
||||
Added since launch, on the strength of the release thread (`docs/FEEDBACK.md` § P1): Infinity Nikki
|
||||
(`nikki`), Persona 5: The Phantom X (`p5x`), Reverse: 1999 (`r1999`). **`GameId` in
|
||||
`src/shared/schema.ts` is the live answer** and `SOURCES` says which of them actually have a source —
|
||||
this table is the launch scope, not a roster to keep in sync.
|
||||
(`nikki`), Persona 5: The Phantom X (`p5x`), Reverse: 1999 (`r1999`), Blue Archive (`ba`).
|
||||
**`GameId` in `src/shared/schema.ts` is the live answer** and `SOURCES` says which of them actually
|
||||
have a source — this table is the launch scope, not a roster to keep in sync.
|
||||
|
||||
Adding a game must require no change to `GachaEvent` — only a `GameId` entry, its `games.ts`
|
||||
metadata, and a source registration. That is the test of whether the data model is right, and it has
|
||||
held: the ten games here have cost the event schema nothing. Per-game *metadata* does occasionally
|
||||
held: the eleven games here have cost the event schema nothing. Per-game *metadata* does occasionally
|
||||
grow (Reverse: 1999 needed `resetHourLocal` for a 05:00 reset), which is a different file and moves
|
||||
no stored key. A game may have several sources; see `docs/INGESTION.md` § Three layers.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user