""" api/main.py — FastAPI backend for feelin' """ from __future__ import annotations from fastapi import FastAPI, BackgroundTasks, HTTPException from fastapi.staticfiles import StaticFiles from pydantic import BaseModel from pathlib import Path import sys sys.path.insert(0, str(Path(__file__).parent.parent)) from data.db import init_db, get_leaderboard, get_latest_podcast, get_stats ,SEG_DIR, POD_DIR from agents.graph import run_post_pipeline BASE_DIR = Path(__file__).parent.parent app = FastAPI(title="feelin' API", version="1.0") # Serve static podcast/segment files static_dir = BASE_DIR / "static" static_dir.mkdir(parents=True, exist_ok=True) app.mount("/static", StaticFiles(directory=str(static_dir)), name="static") # Init DB on startup @app.on_event("startup") def on_startup(): init_db() # ── Models ────────────────────────────────────────────────────────────────── class PostRequest(BaseModel): text: str class PodcastRequest(BaseModel): category: str # ── Routes ────────────────────────────────────────────────────────────────── @app.get("/health") def health(): return {"status": "ok"} @app.post("/post") def submit_post(req: PostRequest): if not req.text or len(req.text.strip()) < 10: raise HTTPException(status_code=400, detail="Post too short.") result = run_post_pipeline(req.text.strip()) return result @app.get("/leaderboard/{category}") def leaderboard_category(category: str, limit: int = 10): valid = ["hilarious", "tragic", "unhinged", "awkward", "chaotic"] if category not in valid: raise HTTPException(status_code=400, detail="Invalid category.") posts = get_leaderboard(category, limit=limit) return {"category": category, "posts": posts} @app.get("/leaderboard") def leaderboard_all(): result = {} for cat in ["hilarious", "tragic", "unhinged", "awkward", "chaotic"]: result[cat] = get_leaderboard(cat, limit=5) return result @app.post("/podcast/generate") def generate_podcast_endpoint(req: PodcastRequest, background_tasks: BackgroundTasks): valid = ["hilarious", "tragic", "unhinged", "awkward", "chaotic"] if req.category not in valid: raise HTTPException(status_code=400, detail="Invalid category.") def _safe_generate(cat: str): try: from podcast.builder import generate_podcast generate_podcast(cat) except Exception as e: print(f"[Podcast background error] {e}") background_tasks.add_task(_safe_generate, req.category) return {"status": "generating", "category": req.category} @app.get("/podcast/{category}") def get_podcast(category: str): valid = ["hilarious", "tragic", "unhinged", "awkward", "chaotic"] if category not in valid: raise HTTPException(status_code=400, detail="Invalid category.") pod = get_latest_podcast(category) if not pod: return {"status": "not_ready", "message": "No episode generated yet. Click ⚡ to generate."} audio_path = pod.get("audio_path", "") audio_url = f"/{audio_path}" if audio_path else None return { "status": "ready", "category": category, "audio_url": audio_url, "script": pod.get("script", ""), "post_count": pod.get("post_count", 0), "created_at": pod.get("created_at", ""), } @app.get("/stats") def stats(): return get_stats()