#!/usr/bin/env python3 """ API Discovery Script — walk the RapidAPI top-down, save raw responses. Workflow: 1. Search for leagues (MLS, Premier League) → get league IDs 2. Search for teams (Toronto FC, Arsenal) → get team IDs 3. Get league matches → find recent past + upcoming event IDs 4. Get match detail, score, stats, location for a finished match 5. Get match highlights (goals, cards, events) 6. Get lineups for a finished match 7. Get squad roster + sample player detail 8. Get standings Saves every response to docs/api_samples/{step}_{endpoint}.json Cost: ~18 API calls """ import sys import json from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) from nike import rapidapi as rapi SAMPLES_DIR = Path(__file__).resolve().parent.parent / "docs" / "api_samples" SAMPLES_DIR.mkdir(parents=True, exist_ok=True) def save(name: str, data) -> None: """Save raw API response to a JSON file.""" path = SAMPLES_DIR / f"{name}.json" with open(path, "w") as f: json.dump(data, f, indent=2, default=str) size_kb = path.stat().st_size / 1024 print(f" ✓ Saved {path.name} ({size_kb:.1f} KB)") def extract_id(data, label="item") -> int | None: """Try to pull an ID from the first search result.""" resp = data.get("response") if isinstance(data, dict) else None # Handle nested response structures items = [] if isinstance(resp, dict): for key in ("suggestions", "teams", "leagues", "players", "matches"): if key in resp and isinstance(resp[key], list) and resp[key]: items = resp[key] break if not items: items = [resp] elif isinstance(resp, list): items = resp else: # Try alternate envelope keys for key in ("data", "result"): val = data.get(key) if isinstance(val, list) and val: items = val break for item in items: if isinstance(item, dict): eid = item.get("id") or item.get("primaryId") if eid: name = item.get("name") or item.get("title") or "?" print(f" → {label}: {name} (ID: {eid})") return int(eid) print(f" ⚠ Could not extract ID from {label} response") # Dump top-level keys for debugging if isinstance(data, dict): print(f" Top-level keys: {list(data.keys())}") if isinstance(resp, dict): print(f" response keys: {list(resp.keys())}") return None def find_event_ids(data, limit=2): """Extract event IDs from a matches/fixtures response.""" resp = data.get("response") if isinstance(data, dict) else None events = {"past": [], "upcoming": []} items = [] if isinstance(resp, dict): for key in ("matches", "events", "fixtures", "allMatches"): if key in resp and isinstance(resp[key], list): items = resp[key] break if not items: # Flatten if resp itself contains sub-lists for key, val in resp.items(): if isinstance(val, list) and val and isinstance(val[0], dict): items = val break elif isinstance(resp, list): items = resp else: for key in ("data", "result"): val = data.get(key) if isinstance(val, list): items = val break for item in items: if not isinstance(item, dict): continue eid = item.get("id") or item.get("eventId") or item.get("primaryId") if not eid: continue # Detect finished vs upcoming status = item.get("status", {}) if isinstance(status, dict): finished = (status.get("finished", False) or status.get("short") == "FT" or status.get("type") == "finished") elif isinstance(status, str): finished = status.lower() in ("ft", "aet", "pen", "finished") else: finished = False bucket = "past" if finished else "upcoming" events[bucket].append(int(eid)) return {k: v[:limit] for k, v in events.items()} def main(): print("=" * 60) print(" Nike API Discovery — Mapping Response Structures") print("=" * 60) # ══════════════════════════════════════════════════════ # STEP 1: League discovery # ══════════════════════════════════════════════════════ print("\n[1/8] Searching for leagues...") mls = rapi.search_leagues("MLS") save("01_search_leagues_mls", mls) mls_id = extract_id(mls, "MLS") epl = rapi.search_leagues("Premier League") save("01_search_leagues_epl", epl) epl_id = extract_id(epl, "Premier League") popular = rapi.get_popular_leagues() save("01_popular_leagues", popular) # ══════════════════════════════════════════════════════ # STEP 2: Team discovery # ══════════════════════════════════════════════════════ print("\n[2/8] Searching for teams...") tfc = rapi.search_teams("Toronto FC") save("02_search_teams_tfc", tfc) tfc_id = extract_id(tfc, "Toronto FC") ars = rapi.search_teams("Arsenal") save("02_search_teams_arsenal", ars) ars_id = extract_id(ars, "Arsenal") # ══════════════════════════════════════════════════════ # STEP 3: League matches (fixtures) # ══════════════════════════════════════════════════════ print("\n[3/8] Fetching league matches...") mls_events = {"past": [], "upcoming": []} if mls_id: mls_matches = rapi.get_league_matches(mls_id) save("03_league_matches_mls", mls_matches) mls_events = find_event_ids(mls_matches) print(f" → Events found: {len(mls_events['past'])} past, " f"{len(mls_events['upcoming'])} upcoming") if not mls_events["past"] and not mls_events["upcoming"]: # Dump structure hints to help debug resp = mls_matches.get("response") if isinstance(resp, dict): print(f" response keys: {list(resp.keys())}") for k, v in resp.items(): if isinstance(v, list) and v: print(f" response.{k}[0] keys: " f"{list(v[0].keys()) if isinstance(v[0], dict) else type(v[0])}") elif isinstance(resp, list) and resp: print(f" response[0] keys: " f"{list(resp[0].keys()) if isinstance(resp[0], dict) else type(resp[0])}") else: print(" ⚠ No MLS ID, skipping") # ══════════════════════════════════════════════════════ # STEP 4: Match detail (finished match) # ══════════════════════════════════════════════════════ print("\n[4/8] Fetching match detail...") event_id = None if mls_events["past"]: event_id = mls_events["past"][0] elif mls_events["upcoming"]: event_id = mls_events["upcoming"][0] if event_id: print(f" Using event ID: {event_id}") detail = rapi.get_match_detail(event_id) save("04_match_detail", detail) score = rapi.get_match_score(event_id) save("04_match_score", score) status = rapi.get_match_status(event_id) save("04_match_status", status) location = rapi.get_match_location(event_id) save("04_match_location", location) else: print(" ⚠ No event ID found — skipping match detail") # ══════════════════════════════════════════════════════ # STEP 5: Match stats + highlights (goals, cards, events) # ══════════════════════════════════════════════════════ print("\n[5/8] Fetching match stats & highlights...") if event_id: stats = rapi.get_match_stats(event_id) save("05_match_stats", stats) highlights = rapi.get_match_highlights(event_id) save("05_match_highlights", highlights) referee = rapi.get_match_referee(event_id) save("05_match_referee", referee) else: print(" ⚠ Skipping (no event ID)") # ══════════════════════════════════════════════════════ # STEP 6: Lineups # ══════════════════════════════════════════════════════ print("\n[6/8] Fetching lineups...") if event_id: home_lineup = rapi.get_home_lineup(event_id) save("06_lineup_home", home_lineup) away_lineup = rapi.get_away_lineup(event_id) save("06_lineup_away", away_lineup) else: print(" ⚠ Skipping (no event ID)") # ══════════════════════════════════════════════════════ # STEP 7: Squad & player detail # ══════════════════════════════════════════════════════ print("\n[7/8] Fetching squad & player detail...") player_id = None if tfc_id: squad = rapi.get_squad(tfc_id) save("07_squad_tfc", squad) # Extract a player ID from the squad response resp = squad.get("response") if isinstance(squad, dict) else None if isinstance(resp, list) and resp: for p in resp: if isinstance(p, dict): pid = p.get("id") or p.get("primaryId") if pid: player_id = int(pid) print(f" → Sample player: {p.get('name', '?')} (ID: {player_id})") break elif isinstance(resp, dict): # May be nested under squad/players/roster for key in ("squad", "players", "roster", "members"): if key in resp and isinstance(resp[key], list): for p in resp[key]: if isinstance(p, dict): pid = p.get("id") or p.get("primaryId") if pid: player_id = int(pid) print(f" → Sample player: {p.get('name', '?')} " f"(ID: {player_id})") break break if not player_id: print(f" response keys: {list(resp.keys())}") if player_id: player = rapi.get_player_detail(player_id) save("07_player_detail", player) else: print(" ⚠ Could not find a player ID in squad response") else: print(" ⚠ No TFC ID, skipping") # ══════════════════════════════════════════════════════ # STEP 8: Standings # ══════════════════════════════════════════════════════ print("\n[8/8] Fetching standings...") if mls_id: standings = rapi.get_standings(mls_id) save("08_standings_mls", standings) # ══════════════════════════════════════════════════════ # Summary # ══════════════════════════════════════════════════════ print("\n" + "=" * 60) files = sorted(SAMPLES_DIR.glob("*.json")) print(f" Saved {len(files)} response samples to docs/api_samples/") for f in files: size_kb = f.stat().st_size / 1024 print(f" {f.name:.<50} {size_kb:.1f} KB") print("=" * 60) print("\n Discovered IDs:") print(f" MLS league ID : {mls_id}") print(f" EPL league ID : {epl_id}") print(f" Toronto FC team ID : {tfc_id}") print(f" Arsenal team ID : {ars_id}") if event_id: print(f" Sample event ID : {event_id}") if player_id: print(f" Sample player ID : {player_id}") print() if __name__ == "__main__": main()