feat: add Game8 parser with Genshin and NTE adapters

Parsers are keyed by site template, not game: one Game8 parser serves
every Game8 page, and adapters bind a URL and game to a parser. Adding a
source for a known site is one SOURCES entry.

Game8 uses at least three templates. This handles label/value detail
tables (Genshin, 9 events) and column tables (NTE, 13 events). Its
image-grid schedule has no year and no end date, so Arknights: Endfield
is not supportable from that source and gets no adapter.

canParse is a structural tripwire: a site redesign fails the run loudly
instead of publishing an empty calendar that reads as "no events".

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
Lucas Winther
2026-08-15 00:10:53 +02:00
co-authored by Claude Opus 5
parent caefe6b0d7
commit 489ce92ef5
12 changed files with 9274 additions and 0 deletions
@@ -0,0 +1,191 @@
[
{
"id": "genshin:to-temper-thyself-and-journey-far:2026-08-10",
"game": "genshin",
"title": "To Temper Thyself and Journey Far",
"type": "other",
"summary": null,
"startsAt": "2026-08-10T00:00:00.000Z",
"startPrecision": "day",
"endsAt": "2026-11-02T00:00:00.000Z",
"endPrecision": "day",
"regionScoped": false,
"regionEnds": null,
"sourceUrl": "https://game8.co/games/Genshin-Impact/archives/301601",
"sourceId": "genshin-game8-events",
"status": "published",
"confidence": 0.85,
"extractionMethod": "parser",
"version": 1,
"firstSeenAt": "2026-08-14T00:00:00.000Z",
"updatedAt": "2026-08-14T00:00:00.000Z"
},
{
"id": "genshin:battle-pass-frostfarer:2026-08-12",
"game": "genshin",
"title": "Battle Pass - Frostfarer",
"type": "other",
"summary": null,
"startsAt": "2026-08-12T00:00:00.000Z",
"startPrecision": "day",
"endsAt": "2026-09-21T00:00:00.000Z",
"endPrecision": "day",
"regionScoped": false,
"regionEnds": null,
"sourceUrl": "https://game8.co/games/Genshin-Impact/archives/301601",
"sourceId": "genshin-game8-events",
"status": "published",
"confidence": 0.85,
"extractionMethod": "parser",
"version": 1,
"firstSeenAt": "2026-08-14T00:00:00.000Z",
"updatedAt": "2026-08-14T00:00:00.000Z"
},
{
"id": "genshin:character-test-runs:2026-08-12",
"game": "genshin",
"title": "Character Test Runs",
"type": "challenge",
"summary": null,
"startsAt": "2026-08-12T00:00:00.000Z",
"startPrecision": "day",
"endsAt": "2026-09-01T00:00:00.000Z",
"endPrecision": "day",
"regionScoped": false,
"regionEnds": null,
"sourceUrl": "https://game8.co/games/Genshin-Impact/archives/301601",
"sourceId": "genshin-game8-events",
"status": "published",
"confidence": 0.85,
"extractionMethod": "parser",
"version": 1,
"firstSeenAt": "2026-08-14T00:00:00.000Z",
"updatedAt": "2026-08-14T00:00:00.000Z"
},
{
"id": "genshin:mutual-aid-in-bloom-into-the-frostlands:2026-08-12",
"game": "genshin",
"title": "Mutual Aid in Bloom: Into the Frostlands",
"type": "other",
"summary": null,
"startsAt": "2026-08-12T00:00:00.000Z",
"startPrecision": "day",
"endsAt": "2026-08-24T00:00:00.000Z",
"endPrecision": "day",
"regionScoped": false,
"regionEnds": null,
"sourceUrl": "https://game8.co/games/Genshin-Impact/archives/301601",
"sourceId": "genshin-game8-events",
"status": "published",
"confidence": 0.85,
"extractionMethod": "parser",
"version": 1,
"firstSeenAt": "2026-08-14T00:00:00.000Z",
"updatedAt": "2026-08-14T00:00:00.000Z"
},
{
"id": "genshin:snezhnaya-travel-guide-web-event:2026-08-12",
"game": "genshin",
"title": "Snezhnaya Travel Guide Web Event",
"type": "other",
"summary": null,
"startsAt": "2026-08-12T00:00:00.000Z",
"startPrecision": "day",
"endsAt": "2026-08-25T00:00:00.000Z",
"endPrecision": "day",
"regionScoped": false,
"regionEnds": null,
"sourceUrl": "https://game8.co/games/Genshin-Impact/archives/301601",
"sourceId": "genshin-game8-events",
"status": "published",
"confidence": 0.85,
"extractionMethod": "parser",
"version": 1,
"firstSeenAt": "2026-08-14T00:00:00.000Z",
"updatedAt": "2026-08-14T00:00:00.000Z"
},
{
"id": "genshin:stygian-onslaught:2026-08-19",
"game": "genshin",
"title": "Stygian Onslaught",
"type": "challenge",
"summary": null,
"startsAt": "2026-08-19T00:00:00.000Z",
"startPrecision": "day",
"endsAt": "2026-09-22T00:00:00.000Z",
"endPrecision": "day",
"regionScoped": false,
"regionEnds": null,
"sourceUrl": "https://game8.co/games/Genshin-Impact/archives/301601",
"sourceId": "genshin-game8-events",
"status": "published",
"confidence": 0.85,
"extractionMethod": "parser",
"version": 1,
"firstSeenAt": "2026-08-14T00:00:00.000Z",
"updatedAt": "2026-08-14T00:00:00.000Z"
},
{
"id": "genshin:great-expeditionist-challenge:2026-08-28",
"game": "genshin",
"title": "Great Expeditionist Challenge",
"type": "challenge",
"summary": null,
"startsAt": "2026-08-28T00:00:00.000Z",
"startPrecision": "day",
"endsAt": "2026-09-14T00:00:00.000Z",
"endPrecision": "day",
"regionScoped": false,
"regionEnds": null,
"sourceUrl": "https://game8.co/games/Genshin-Impact/archives/301601",
"sourceId": "genshin-game8-events",
"status": "published",
"confidence": 0.85,
"extractionMethod": "parser",
"version": 1,
"firstSeenAt": "2026-08-14T00:00:00.000Z",
"updatedAt": "2026-08-14T00:00:00.000Z"
},
{
"id": "genshin:trial-of-the-bastion:2026-09-07",
"game": "genshin",
"title": "Trial of the Bastion",
"type": "challenge",
"summary": null,
"startsAt": "2026-09-07T00:00:00.000Z",
"startPrecision": "day",
"endsAt": "2026-09-17T00:00:00.000Z",
"endPrecision": "day",
"regionScoped": false,
"regionEnds": null,
"sourceUrl": "https://game8.co/games/Genshin-Impact/archives/301601",
"sourceId": "genshin-game8-events",
"status": "published",
"confidence": 0.85,
"extractionMethod": "parser",
"version": 1,
"firstSeenAt": "2026-08-14T00:00:00.000Z",
"updatedAt": "2026-08-14T00:00:00.000Z"
},
{
"id": "genshin:overflowing-abundance-rerun:2026-09-14",
"game": "genshin",
"title": "Overflowing Abundance Rerun",
"type": "rerun",
"summary": null,
"startsAt": "2026-09-14T00:00:00.000Z",
"startPrecision": "day",
"endsAt": "2026-09-21T00:00:00.000Z",
"endPrecision": "day",
"regionScoped": false,
"regionEnds": null,
"sourceUrl": "https://game8.co/games/Genshin-Impact/archives/301601",
"sourceId": "genshin-game8-events",
"status": "published",
"confidence": 0.85,
"extractionMethod": "parser",
"version": 1,
"firstSeenAt": "2026-08-14T00:00:00.000Z",
"updatedAt": "2026-08-14T00:00:00.000Z"
}
]