BikeControl (SwiftControl)
Use Zwift Click, Zwift Play, Shimano Di2, or any Bluetooth controller with MyWhoosh, Rouvy, Zwift, and more. Free to try on iOS, Android, Windows, and macOS.
A comprehensive automation tool for generating and maintaining Formula One Wiki tables on f1.fandom.com
Sports & fitnessTypeScript · HTMLGitHub @sYnVerseOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗A comprehensive automation tool for generating and maintaining Formula One Wiki tables on f1.fandom.com. This project combines TypeScript (Cloudflare Workers) and Python to create fully formatted WikiTables for Grand Prix articles.
Template:Latest_F1_News/Events.Template:Latest_Data (number = season round, gp = latest completed GP link, gpnumber incremented by 1 per completed round).Template:Career_Results/Points/2026, Template:Career_Results/Position/2026, and Template:Career_Results/Team_Position/2026) synchronized with round-verified standings from the Jolpi API, with ownership strictly gated to the latest concluded round to prevent multi-round flip-flops.|Name = {{TD}} rows to Template:Career_Results/{year} {race} when test drivers participate in FP1, preserving existing {{TD}} rows during race results writes.Infobox_Race or Infobox Sprint Race) for qualifying pole, sprint standings, race winners, podium finishes, and fastest laps as sessions conclude.Background, FP1, FP2, FP3, Q1, Q2, Q3, Sprint Report, and Race Report) using an LLM. Practice reports crawl official F1.com session articles for richer context. Features native Cloudflare Workers AI (Llama 3) support with failover to Google Gemini or OpenAI APIs. Checks and safeguards sections to ensure human edits are never overwritten.Category:Subtemplates of Template:Stats (e.g. Championships, Distance, DistanceLed, Doubles, Entries, FastestLaps, FrontRows, Grand Chelems, HatTricks, Laps, LapsLed, Podiums, Points, Poles, RacesLed, SprintFastestLaps, SprintPodiums, SprintPoles, SprintWins, Starts, Wins).User:…/Sandbox drafts).TURNSTILE_SECRET_KEY is not configured). Optional DASHBOARD_OWNER_TOKEN adds an extra shared-secret gate for publish APIs.sessionStorage only (cleared when the tab closes); domain/username/sandbox settings may persist in localStorage.1278 + round for Rounds 1–3, 1280 + round for Rounds 4–22).f1-fandom/
├── src/
│ ├── index.ts # Main Cloudflare Worker handler and cron sync
│ ├── career-results-stint.ts # Stint-aware Career Results row sync helpers
│ ├── career-standings-owner.ts # Latest concluded round ownership helper for career standings
│ ├── f1-api.ts # Jolpi API integration, Ergast fallbacks, and F1.com helpers
│ ├── f1-api-cache.ts # Within-run API deduplication and 429 backoff
│ ├── fia-pdf-parser.ts # FIA Entry List PDF parsing for test and race drivers
│ ├── sync-kv.ts # Per-target KV sync flag helpers
│ ├── kv-ops.ts # KV daily write count, log buffering, edit retry/replay, and failure locks
│ ├── llm-reporter.ts # LLM prompts, F1.com article crawling, HTML sanitization
│ ├── publish-guard.ts # Dashboard publish title/credential/rate-limit guards
│ ├── season-roster-2026.ts # Shared 2026 driver-to-constructor roster map
│ ├── stats.ts # Driver career statistics and template calculations
│ ├── statsf1.ts # StatsF1 classification verification helper
│ ├── team-drivers-registry.ts # Template:Team Drivers/{year} stint registry parser
│ ├── url-allowlist.ts # Strict https host/URL allowlisting helpers
│ ├── wiki.ts # MediaWiki API integration, domain allowlist, and edit retries
│ ├── wikitext-generator.ts # WikiTable formatting and test driver helpers
│ ├── wikitext-parse.ts # CodeQL-safe line-based wikitext parsing
│ ├── wikitext-sanitize.ts # Sanitize API strings before wikitext interpolation
│ └── frontend-html.ts # Web dashboard UI
├── scripts/
│ ├── verify-sync-kv.ts # KV sync flag smoke tests
│ ├── verify-career-standings-owner.ts # Multi-round career standings ownership tests
│ ├── verify-career-stint.ts # Career Results stint-aware sync tests
│ ├── verify-wikitext-parse.ts # Wikitext parsing verification
│ ├── verify-infobox-update.ts # Infobox parameter read/update tests
│ ├── verify-jolpica-cache.ts # API cache dedup, backoff, and bulk endpoint tests
│ ├── verify-practice-sessions.ts # Practice scraping and test driver tests
│ ├── verify-openf1-sync.ts # OpenF1 Sprint Qualifying sync and wikitext tests
│ ├── verify-latest-data.ts # Template:Latest_Data parse/increment tests
│ ├── verify-llm-reporter.ts # HTML sanitization and prompt context tests
│ ├── verify-entry-list-sync.ts # Entry list table sync and PDF parser tests
│ ├── verify-fia-pdf-parser.ts # FIA Entry List PDF parser verification
│ ├── verify-kv-ops.ts # KV daily write count and edit failure lock tests
│ ├── verify-wiki-edit-retry.ts # Edit retry and KV replay queue verification
│ ├── verify-wiki-domain-allowlist.ts # Wiki domain SSRF allowlist tests
│ ├── verify-security-hardening.ts # Publish/practice URL/sanitize hardening tests
│ ├── verify-career-placeholder.ts # Career Results placeholder row tests
│ ├── verify-legacy-kv.ts # Legacy KV state fallback tests
│ └── verify-stats-sync.ts # Career stats template calculations verification
├── f1.py # Python wiki table generator
├── pyergast.py # Python Ergast API wrapper
├── wrangler.toml # Cloudflare Worker name, crons, KV, public vars
└── README.md
npm run deploy / wrangler deploy) to enable cron sync and the dashboard.Public vars (also settable in wrangler.toml [vars]):
| Name | Purpose |
|---|---|
DEFAULT_WIKI_DOMAIN | Default wiki host (default f1.fandom.com) |
TURNSTILE_SITE_KEY | Cloudflare Turnstile site key for the dashboard |
STATS_SYNC | Set to TRUE to enable cron updates of the 21 career Stats templates |
ALLOWED_WIKI_HOSTS | Optional comma-separated extra allowlisted wiki hostnames |
LLM_PROVIDER | Optional preferred LLM (gemini, openai, or workers-ai) |
Secrets (via Cloudflare dashboard or wrangler secret put — never commit values):
| Name | Purpose |
|---|---|
WIKI_BOT_USERNAME | MediaWiki bot account used by cron and (when set) dashboard publish binding |
WIKI_BOT_PASSWORD | Bot password for that account |
TURNSTILE_SECRET_KEY | Turnstile server-side verification secret |
DASHBOARD_OWNER_TOKEN | Optional shared secret required on /api/publish and /api/publish-stats |
GEMINI_API_KEY / OPENAI_API_KEY | Optional LLM provider keys (Workers AI is used when neither is set) |
RESEND_API_KEY | Optional; enables daily operations summary email |
JOLPICA_API_KEY | Optional Jolpi/Jolpica API bearer token |
WIKI_API_ENDPOINT / PROXY_SECRET | Optional MediaWiki API proxy URL and shared proxy header |
Cron triggers (see wrangler.toml): */21 * * * * (high-frequency race-weekend polling) and 0 * * * * (hourly). Bind KV namespace F1_WIKI_STATE and the Workers AI binding as configured in wrangler.toml.
npm test
This runs the TypeScript compiler (tsc --noEmit) and the verification scripts wired in package.json test. Additional security suites can be run directly:
npx tsx scripts/verify-wiki-domain-allowlist.ts
npx tsx scripts/verify-security-hardening.ts
Summary of improvements (updated October 20, 2026):
/api/wiki-status and /api/wiki-content accept only allowlisted hosts (default f1.fandom.com, plus DEFAULT_WIKI_DOMAIN / ALLOWED_WIKI_HOSTS) with strict https-only parsing; same-host redirect following on wiki page fetches./api/publish and /api/publish-stats enforce wiki host allowlisting, allowlisted page titles, wikitext size limits, per-IP rate limiting, Turnstile, optional DASHBOARD_OWNER_TOKEN, and credential binding to WIKI_BOT_USERNAME / WIKI_BOT_PASSWORD when those secrets are configured.https://www.formula1.com/en/results/.../practice/....api.openf1.org with path traversal rejection.sessionStorage; non-secret settings may remain in localStorage."Semi-automated edit..." instead of "automated update".Paul AronARO) produced when falling back to F1.com scrapes during OpenF1 429 errors, ensuring accurate nationality flag mapping and KV cache lookups.getTeamTemplate.session_result OpenF1 KV cache TTL from 1 day to 30 days to reduce upstream API load.result === 'Success').Points, Position, and Team_Position by updating Career standings in the same pass as race results and restricting standings ownership strictly to the latest concluded round.|Name = {{TD}} rows to Template:Career_Results/{year} {race} when test drivers participate in FP1, preserving existing {{TD}} rows during post-race results writes.Template:Latest_Data (number, gp, gpnumber) after each completed Grand Prix.TestDriverEntry rows (names, flags, constructor teams) in KV per round during Entry List sync, ensuring practice tables reuse accurate driver details instead of defaulting to {{FIA}}.Ryo Hirakawa to Ryō Hirakawa) to match Fandom article titles./drivers/{id}/constructors.json endpoint calls and prior-round driver walks by deriving driver grids directly from already-fetched season standings, results, and qualifying payloads.season-roster-2026.ts, and requires verified race results before publishing season standings.api.openf1.org to retrieve Sprint Qualifying classifications.generateSprintQualifyingWikitext to compile results into a structured wikitext table with SQ1/SQ2/SQ3 segment classification times, 107% time calculations, and official FIA source reference.verify-openf1-sync.ts test suite to the project test runner to verify time formatting and wikitext table compilation.TEAM_DETAILS_2026 with finalized chassis designations (e.g., Cadillac MAC-26) and engine models (e.g., Red Bull Ford DM01, Audi AFR 26, Honda RA626H) for the 2026 season.runInPool with concurrency limit of 7).STATS_SYNC environment gate variable; when not set to TRUE, the scheduled worker skips all KV checks, Jolpica fetches, and edits to the 21 career stats templates.src/kv-ops.ts) with a threshold (MAX_EDIT_FAILURES = 3) to block wiki edits to pages experiencing persistent issues, preventing API token locking or quota depletion.Doubles, HatTricks, and Grand Chelems templates automatically.getF1RacingKey, getF1comRaceId) across frontend and backend, resolving Japan and Abu Dhabi slug inconsistencies.{{FIA}} and trigger a daily email warning.1278 + round for Rounds 1–3, 1280 + round for Rounds 4–22) in both TypeScript worker and Python CLI.sync-kv.ts): Replaced monolithic gp_updated flag with dedicated flags per GP page section, career template, stats template, and standings template — preventing one successful sync from blocking retries for another target.Retry-After, round-level KV early-skip, and batched fetchRoundJolpicaData to reduce API calls during cron runs.Template:Latest_F1_News/Events from reverting to stale prior-season data when adjacent-year schedule fetches fail.wikitext-parse.ts, wiki.ts, stats.ts, and index.ts.indexOf instead of regular expressions on untrusted wikitext.}}}} corruption when template values contain nested }} braces..github/dependabot.yml.Built for Formula One Wiki enthusiasts and contributors.