Add complete Nike football data platform with: - FastMCP server exposing football data tools over HTTP - RapidAPI client for free-api-live-football-data integration - Bootstrap web dashboard with live match/standings views - REST API endpoints for dashboard consumption - Docker support with multi-stage build - Comprehensive README with architecture docs - Minimal .gitignore replacing verbose Python template
76 lines
3.1 KiB
Python
76 lines
3.1 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Test API connectivity, find Toronto FC, and list popular leagues
|
|
so we can confirm the correct MLS league ID for this API.
|
|
|
|
Uses 2 API quota calls.
|
|
"""
|
|
import json
|
|
import sys
|
|
import time
|
|
from pathlib import Path
|
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
|
|
|
from nike import config, api_football
|
|
|
|
|
|
def main() -> None:
|
|
if not config.API_FOOTBALL_KEY:
|
|
print("❌ API_FOOTBALL_KEY not set in .env")
|
|
sys.exit(1)
|
|
|
|
print(f"API: {config.API_FOOTBALL_BASE}\n")
|
|
|
|
# ── 1. Popular leagues (connectivity probe + league ID discovery) ──
|
|
print("── Popular Leagues ──────────────────────────")
|
|
try:
|
|
t0 = time.time()
|
|
data = api_football._get("football-popular-leagues", timeout=8)
|
|
latency_ms = round((time.time() - t0) * 1000, 1)
|
|
except Exception as e:
|
|
print(f"❌ Not connected: {e}")
|
|
sys.exit(1)
|
|
|
|
print(f"✅ Connected latency={latency_ms}ms "
|
|
f"quota_remaining={api_football.last_quota_remaining()}")
|
|
|
|
leagues = (data.get('response', {}).get('popular') or
|
|
data.get('response', {}).get('leagues') or [])
|
|
if not isinstance(leagues, list):
|
|
print(f" Raw response structure:\n{json.dumps(data, indent=2)[:1000]}")
|
|
else:
|
|
print(f" {len(leagues)} league(s) returned:")
|
|
for lg in leagues:
|
|
lg_id = lg.get('id', '?')
|
|
lg_name = lg.get('name', str(lg))
|
|
ccode = lg.get('ccode', '')
|
|
print(f" [{str(lg_id):>5}] {lg_name} ({ccode})")
|
|
print(f"\n ↳ Current config.MLS_LEAGUE_ID = {config.MLS_LEAGUE_ID}")
|
|
print(" Update nike/config.py if the ID above doesn't match MLS.\n")
|
|
|
|
# ── 2. Search for Toronto FC ───────────────────────────────────
|
|
print("── Search: Toronto ──────────────────────────")
|
|
raw_search = api_football._get("football-teams-search", {"search": "Toronto"})
|
|
print(f" quota_remaining={api_football.last_quota_remaining()}")
|
|
|
|
# Try all common envelope keys; fall back to full raw dump
|
|
raw_list = (raw_search.get('response', {}).get('suggestions') or
|
|
raw_search.get('response', {}).get('teams') or
|
|
raw_search.get('data') or raw_search.get('result'))
|
|
if not isinstance(raw_list, list) or not raw_list:
|
|
print(f" 0 results — raw response:\n{json.dumps(raw_search, indent=2)[:1500]}")
|
|
else:
|
|
teams = [api_football._normalise_team_item(t)
|
|
for t in raw_list if t.get('type', 'team') == 'team']
|
|
print(f" {len(teams)} team result(s):")
|
|
for item in teams:
|
|
t = item['team']
|
|
v = item.get('venue') or {}
|
|
print(f" [{str(t.get('id')):>6}] {t.get('name')} ({t.get('country')})")
|
|
if v.get('name'):
|
|
print(f" Venue: {v.get('name')}, {v.get('city')} cap={v.get('capacity')}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|