LiberoSports/FPLAIManager
0
1"""Validate live official FPL API responses used by the application.2 3Run from the project root: ``python scripts/validate_fpl_api.py``.4"""5 6from __future__ import annotations7 8import argparse9import json10import sys11from pathlib import Path12 13PROJECT_ROOT = Path(__file__).resolve().parents[1]14if str(PROJECT_ROOT) not in sys.path:15 sys.path.insert(0, str(PROJECT_ROOT))16 17from data.fpl_api import FPLAPIClient, FPLAPIError18 19 20def health_dict(health: object) -> dict[str, object]:21 return health.model_dump(mode="json") # type: ignore[attr-defined]22 23 24def main() -> int:25 parser = argparse.ArgumentParser(description="Validate the official FPL endpoint models.")26 parser.add_argument("--entry-id", type=int, help="Optional known public FPL entry ID to validate entry routes.")27 parser.add_argument("--refresh", action="store_true", help="Bypass the local TTL cache.")28 args = parser.parse_args()29 30 client = FPLAPIClient()31 try:32 snapshot = client.get_snapshot(force_refresh=args.refresh)33 active_event = snapshot.current_or_next_gameweek34 report: dict[str, object] = {35 "bootstrap": health_dict(snapshot.bootstrap_health),36 "fixtures": health_dict(snapshot.fixtures_health),37 "counts": {38 "players": len(snapshot.bootstrap.elements),39 "teams": len(snapshot.bootstrap.teams),40 "events": len(snapshot.bootstrap.events),41 "fixtures": len(snapshot.fixtures),42 },43 "active_or_next_gameweek": active_event.id if active_event else None,44 }45 46 first_player = snapshot.bootstrap.elements[0]47 player_summary, player_health = client.get_player_summary(first_player.id, force_refresh=args.refresh)48 report["element_summary"] = {49 "player_id": first_player.id,50 "player_name": first_player.web_name,51 "history_rows": len(player_summary.history),52 "fixture_rows": len(player_summary.fixtures),53 "health": health_dict(player_health),54 }55 56 if active_event:57 live_event, live_health = client.get_event_live(active_event.id, force_refresh=args.refresh)58 report["event_live"] = {59 "gameweek": active_event.id,60 "live_elements": len(live_event.elements),61 "health": health_dict(live_health),62 }63 64 if args.entry_id:65 try:66 history, history_health = client.get_entry_history(args.entry_id, force_refresh=args.refresh)67 report["entry_history"] = {68 "top_level_keys": sorted(history.keys()),69 "health": health_dict(history_health),70 }71 except FPLAPIError as error:72 report["entry_history"] = {"unavailable": str(error)}73 74 try:75 transfers, transfers_health = client.get_entry_transfers(args.entry_id, force_refresh=args.refresh)76 report["entry_transfers"] = {77 "transfer_rows": len(transfers),78 "health": health_dict(transfers_health),79 }80 except FPLAPIError as error:81 report["entry_transfers"] = {"unavailable": str(error)}82 83 if active_event:84 try:85 picks, picks_health = client.get_entry_picks(86 args.entry_id, active_event.id, force_refresh=args.refresh87 )88 report["entry_picks"] = {89 "pick_count": len(picks.picks),90 "active_chip": picks.active_chip,91 "health": health_dict(picks_health),92 }93 except FPLAPIError as error:94 report["entry_picks"] = {"unavailable": str(error)}95 96 print(json.dumps(report, indent=2, sort_keys=True))97 return 098 except FPLAPIError as error:99 print(f"FPL validation failed: {error}", file=sys.stderr)100 return 1101 102 103if __name__ == "__main__":104 raise SystemExit(main())105 