Spaces:
Running
Running
| from pathlib import Path | |
| import sqlite3 | |
| from typing import Optional | |
| import pandas as pd | |
| from fastapi import FastAPI, Query | |
| from fastapi.middleware.cors import CORSMiddleware | |
| app = FastAPI(title="Green Energy News API", version="1.0.0") | |
| # SQLite stays in the same repo position | |
| BASE_DIR = Path(__file__).resolve().parent.parent | |
| DB_PATH = BASE_DIR / "data" / "news.db" | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], # tighten later if needed | |
| allow_credentials=False, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| def get_connection() -> sqlite3.Connection: | |
| return sqlite3.connect(DB_PATH) | |
| def health(): | |
| return { | |
| "status": "ok", | |
| "db_exists": DB_PATH.exists(), | |
| "db_path": str(DB_PATH), | |
| } | |
| def get_labels(): | |
| conn = get_connection() | |
| query = """ | |
| SELECT DISTINCT label | |
| FROM classified_articles | |
| WHERE label IS NOT NULL | |
| ORDER BY label | |
| """ | |
| df = pd.read_sql_query(query, conn) | |
| conn.close() | |
| return df["label"].dropna().tolist() | |
| def get_sources(): | |
| conn = get_connection() | |
| query = """ | |
| SELECT DISTINCT source | |
| FROM classified_articles | |
| WHERE source IS NOT NULL | |
| ORDER BY source | |
| """ | |
| df = pd.read_sql_query(query, conn) | |
| conn.close() | |
| return df["source"].dropna().tolist() | |
| def daily_actions( | |
| start_date: Optional[str] = None, | |
| end_date: Optional[str] = None, | |
| ): | |
| conn = get_connection() | |
| query = """ | |
| SELECT | |
| date(published_at) AS day, | |
| label, | |
| COUNT(*) AS count | |
| FROM classified_articles | |
| WHERE 1=1 | |
| """ | |
| params = [] | |
| if start_date: | |
| query += " AND date(published_at) >= date(?)" | |
| params.append(start_date) | |
| if end_date: | |
| query += " AND date(published_at) <= date(?)" | |
| params.append(end_date) | |
| query += """ | |
| GROUP BY date(published_at), label | |
| ORDER BY day ASC, label ASC | |
| """ | |
| df = pd.read_sql_query(query, conn, params=params) | |
| conn.close() | |
| return df.to_dict(orient="records") | |
| def get_articles( | |
| label: Optional[str] = None, | |
| source: Optional[str] = None, | |
| start_date: Optional[str] = None, | |
| end_date: Optional[str] = None, | |
| search: Optional[str] = None, | |
| limit: int = Query(50, ge=1, le=500), | |
| offset: int = Query(0, ge=0), | |
| ): | |
| conn = get_connection() | |
| query = """ | |
| SELECT | |
| article_id, | |
| title, | |
| description, | |
| clean_text, | |
| label, | |
| raw_label, | |
| source, | |
| url, | |
| published_at, | |
| classified_at | |
| FROM classified_articles | |
| WHERE 1=1 | |
| """ | |
| params = [] | |
| if label: | |
| query += " AND label = ?" | |
| params.append(label) | |
| if source: | |
| query += " AND source = ?" | |
| params.append(source) | |
| if start_date: | |
| query += " AND date(published_at) >= date(?)" | |
| params.append(start_date) | |
| if end_date: | |
| query += " AND date(published_at) <= date(?)" | |
| params.append(end_date) | |
| if search: | |
| query += " AND (lower(title) LIKE ? OR lower(description) LIKE ?)" | |
| pattern = f"%{search.lower()}%" | |
| params.extend([pattern, pattern]) | |
| query += " ORDER BY published_at DESC LIMIT ? OFFSET ?" | |
| params.extend([limit, offset]) | |
| df = pd.read_sql_query(query, conn, params=params) | |
| conn.close() | |
| return df.to_dict(orient="records") |