|
"""Keyword routes for API endpoints.""" |
|
import logging |
|
from fastapi import APIRouter |
|
from fastapi.responses import JSONResponse |
|
|
|
from collectors.finfast.keyword import collect as run_historical_backfill |
|
from models.database import keywords_collection, summary_collection |
|
|
|
|
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
router = APIRouter(prefix="/keyword", tags=["keyword"]) |
|
|
|
@router.post('/historical-backfill') |
|
async def historical_backfill(): |
|
""" |
|
Manual trigger endpoint for 60-day historical keyword backfill. |
|
|
|
Returns: |
|
JSON response with status and details |
|
""" |
|
try: |
|
logger.info("Received request for historical keyword backfill") |
|
|
|
|
|
run_historical_backfill() |
|
|
|
logger.info("Historical keyword backfill completed successfully") |
|
return JSONResponse(content={ |
|
"status": "success", |
|
"message": "Historical keyword backfill completed successfully", |
|
"details": { |
|
"operation": "60-day historical keyword backfill", |
|
"method": "standard approach (day-by-day processing)" |
|
} |
|
}, status_code=200) |
|
|
|
except Exception as e: |
|
logger.error("Error during historical keyword backfill: %s", e) |
|
return JSONResponse(content={ |
|
"status": "error", |
|
"message": "Failed to complete historical keyword backfill", |
|
"error": str(e) |
|
}, status_code=500) |
|
|
|
@router.get('/status') |
|
async def keyword_status(): |
|
""" |
|
Get status of keyword processing. |
|
|
|
Returns: |
|
JSON response with keyword processing status |
|
""" |
|
try: |
|
|
|
|
|
total_documents = keywords_collection.count_documents({}) |
|
|
|
|
|
oldest_doc = keywords_collection.find_one(sort=[("_id", 1)]) |
|
newest_doc = keywords_collection.find_one(sort=[("_id", -1)]) |
|
|
|
status_info = { |
|
"status": "operational", |
|
"total_keyword_documents": total_documents, |
|
"date_range": { |
|
"oldest": oldest_doc["_id"] if oldest_doc else None, |
|
"newest": newest_doc["_id"] if newest_doc else None |
|
} |
|
} |
|
|
|
return JSONResponse(content=status_info, status_code=200) |
|
|
|
except Exception as e: |
|
logger.error("Error getting keyword status: %s", e) |
|
return JSONResponse(content={ |
|
"status": "error", |
|
"message": "Failed to get keyword status", |
|
"error": str(e) |
|
}, status_code=500) |
|
|
|
@router.get('/summary') |
|
async def get_all_summaries(): |
|
""" |
|
Get all summaries (today, week, month). |
|
|
|
Returns: |
|
JSON response with all summary data |
|
""" |
|
try: |
|
logger.info("Received request for all summaries") |
|
|
|
summaries = {} |
|
periods = ["today", "week", "month"] |
|
|
|
for period in periods: |
|
summary_doc = summary_collection.find_one({"_id": period}) |
|
if summary_doc: |
|
summaries[period] = { |
|
"keywords": summary_doc.get("keywords", []), |
|
"categories": summary_doc.get("categories", []) |
|
} |
|
else: |
|
summaries[period] = { |
|
"keywords": [], |
|
"categories": [], |
|
"message": f"No summary available for {period}" |
|
} |
|
|
|
return JSONResponse(content={ |
|
"status": "success", |
|
"summaries": summaries |
|
}, status_code=200) |
|
|
|
except Exception as e: |
|
logger.error("Error getting all summaries: %s", e) |
|
return JSONResponse(content={ |
|
"status": "error", |
|
"message": "Failed to get summaries", |
|
"error": str(e) |
|
}, status_code=500) |
|
|
|
@router.get('/summary/{period}') |
|
async def get_summary_by_period(period: str): |
|
""" |
|
Get specific summary by period (today/week/month). |
|
|
|
Args: |
|
period: Analysis period (today, week, or month) |
|
|
|
Returns: |
|
JSON response with specific summary data |
|
""" |
|
try: |
|
|
|
valid_periods = ["today", "week", "month"] |
|
if period not in valid_periods: |
|
return JSONResponse(content={ |
|
"status": "error", |
|
"message": "Invalid period. Must be one of: today, week, month", |
|
"valid_periods": valid_periods |
|
}, status_code=400) |
|
|
|
logger.info("Received request for %s summary", period) |
|
|
|
summary_doc = summary_collection.find_one({"_id": period}) |
|
|
|
if summary_doc: |
|
return JSONResponse(content={ |
|
"status": "success", |
|
"period": period, |
|
"summary": { |
|
"keywords": summary_doc.get("keywords", []), |
|
"categories": summary_doc.get("categories", []) |
|
} |
|
}, status_code=200) |
|
return JSONResponse(content={ |
|
"status": "not_found", |
|
"message": f"No summary available for {period}", |
|
"period": period |
|
}, status_code=404) |
|
|
|
except Exception as e: |
|
logger.error("Error getting %s summary: %s", period, e) |
|
return JSONResponse(content={ |
|
"status": "error", |
|
"message": f"Failed to get {period} summary", |
|
"error": str(e) |
|
}, status_code=500) |
|
|