""" Fetch sports odds from The Odds API and save JSON snapshots. Requires ODDS_API_KEY in environment or .env (see project .env.example). Usage: python odds/scripts/fetch_odds.py --sport boxing_boxing --out odds/data/samples/boxing_odds.json """ from __future__ import annotations import argparse import json import os import sys from pathlib import Path try: import requests except ImportError: print("Install dependencies: pip install -r requirements.txt", file=sys.stderr) raise API_BASE = "https://api.the-odds-api.com/v4" DEFAULT_SPORT = "boxing_boxing" DEFAULT_REGIONS = "uk,eu" DEFAULT_MARKETS = "h2h" def get_api_key() -> str: """Read API key from ODDS_API_KEY environment variable.""" key = os.environ.get("ODDS_API_KEY", "").strip() if not key: raise SystemExit( "Missing ODDS_API_KEY. Copy .env.example to .env and set your key." ) return key def fetch_odds( sport: str, regions: str, markets: str, api_key: str, ) -> list[dict]: """ GET odds for a sport from The Odds API. Args: sport: Sport key (e.g. boxing_boxing). regions: Comma-separated region codes. markets: Comma-separated market keys. api_key: The Odds API key. Returns: Parsed JSON list of events. Raises: requests.HTTPError: On non-2xx response. """ url = f"{API_BASE}/sports/{sport}/odds" params = { "apiKey": api_key, "regions": regions, "markets": markets, "oddsFormat": "decimal", } response = requests.get(url, params=params, timeout=60) response.raise_for_status() return response.json() def save_odds(data: list[dict], output_path: Path) -> None: """Write odds JSON to disk with stable formatting.""" output_path.parent.mkdir(parents=True, exist_ok=True) with output_path.open("w", encoding="utf-8") as f: json.dump(data, f, indent=4, ensure_ascii=False) print(f"Saved {len(data)} events to {output_path}") def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser(description="Fetch odds from The Odds API") parser.add_argument("--sport", default=DEFAULT_SPORT, help="Sport key") parser.add_argument("--regions", default=DEFAULT_REGIONS, help="Region codes") parser.add_argument("--markets", default=DEFAULT_MARKETS, help="Market keys") parser.add_argument( "--out", type=Path, default=Path("odds/data/samples/boxing_odds.json"), help="Output JSON path", ) return parser.parse_args() def main() -> None: args = parse_args() api_key = get_api_key() data = fetch_odds(args.sport, args.regions, args.markets, api_key) save_odds(data, args.out) if __name__ == "__main__": main()