from fastapi import FastAPI, HTTPException from fastapi.middleware.cors import CORSMiddleware from apscheduler.schedulers.background import BackgroundScheduler from datetime import datetime import os from dotenv import load_dotenv from huggingface_hub import HfApi import json # Load environment variables load_dotenv() # API configuration API_HOST = os.getenv("API_HOST", "0.0.0.0") API_PORT = int(os.getenv("API_PORT", "3002")) app = FastAPI() # Add CORS middleware app.add_middleware( CORSMiddleware, allow_origins=[ "http://localhost:5173", # Vite dev server f"http://localhost:{API_PORT}", # API port "https://huggingface.co", # HF main domain "https://*.hf.space", # HF Spaces domains ], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Cache storage cache = { "data": None, "last_updated": None } # HF API configuration HF_TOKEN = os.getenv("HUGGING_FACE_HUB_TOKEN") REPO_ID = os.getenv("HUGGING_FACE_STORAGE_REPO") FILE_PATH = os.getenv("HUGGING_FACE_STORAGE_FILE_PATH") CACHE_DURATION_MINUTES = int(os.getenv("UPDATE_INTERVAL_MINUTES", "15")) # Get from env or default to 15 # Initialize HF API client hf_api = HfApi(token=HF_TOKEN) def fetch_leaderboards(): """Fetch leaderboards data from Hugging Face""" try: # Download the JSON file directly json_path = hf_api.hf_hub_download( repo_id=REPO_ID, filename=FILE_PATH, repo_type="dataset" ) with open(json_path, 'r') as f: cache["data"] = json.load(f) cache["last_updated"] = datetime.now() print(f"Cache updated at {cache['last_updated']}") except Exception as e: print(f"Error fetching data: {str(e)}") if not cache["data"]: # Only raise if we don't have any cached data raise HTTPException(status_code=500, detail="Failed to fetch leaderboards data") # Initialize scheduler scheduler = BackgroundScheduler() scheduler.add_job(fetch_leaderboards, 'interval', minutes=CACHE_DURATION_MINUTES) scheduler.start() # Initial fetch fetch_leaderboards() @app.get("/api/leaderboards") async def get_leaderboards(): """Get leaderboards data from cache""" if not cache["data"]: fetch_leaderboards() return { "data": cache["data"], "last_updated": cache["last_updated"].isoformat() if cache["last_updated"] else None } @app.get("/api/health") async def health_check(): """Health check endpoint""" return { "status": "healthy", "cache_status": "initialized" if cache["data"] else "empty", "last_updated": cache["last_updated"].isoformat() if cache["last_updated"] else None } if __name__ == "__main__": import uvicorn uvicorn.run("server:app", host=API_HOST, port=API_PORT, reload=True)