OxbridgeEconomics
added the hot entity retrieve route and handling logic
d055f1a
"""This module defines the /summary route for the Flask application."""
import importlib
from venv import logger
import re
from fastapi import APIRouter, HTTPException, Path
from fastapi.responses import JSONResponse
from controllers.summary import get_summary_data # pylint: disable=import-error
from models.database import knowledge_base # pylint: disable=import-error
router = APIRouter(prefix="/summary", tags=["summary"])
@router.get("/{email}")
async def get_user_document_stats(
email: str = Path(..., description="User's email address")
) -> JSONResponse:
"""
Get document statistics for a specific user.
This endpoint counts the number of unique emails and files uploaded by the user.
It groups documents by metadata.id to ensure unique document counting (not chunks).
Args:
email (str): The user's email address
Returns:
JSONResponse: A JSON response containing document counts:
{
"email": "[email protected]",
"emails": 5,
"files": 12,
"total_documents": 17
}
Raises:
HTTPException: 400 for invalid email, 500 for database errors
"""
try:
email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
if not email or not re.match(email_pattern, email):
raise HTTPException(
status_code=400,
detail="Invalid email format. Must be a valid email address."
)
# Get document counts from database
result = knowledge_base.get_doc_count(email)
# Add email to response
result["email"] = email
return JSONResponse(content=result, status_code=200)
except ValueError as e:
logger.error("Validation error for user %s: %s", email, str(e))
raise HTTPException(status_code=400, detail=str(e)) # pylint: disable=raise-missing-from
except Exception as e: # pylint: disable=broad-exception-caught
logger.error("Database error for user %s: %s", email, str(e))
raise HTTPException( # pylint: disable=raise-missing-from
status_code=500,
detail="Internal server error while retrieving document statistics."
)
@router.get('')
async def get_summary() -> JSONResponse:
"""
Generate a summary dashboard with content flow and entity analysis data.
This endpoint provides a complete summary overview, including:
- Content Flow Tracker: Article counts by source and category
- Entity Analysis: Top entities by type with mentions
All data is returned together, divided into three time periods: today, week, and month.
Returns:
JSONResponse: A JSON response containing the complete summary dashboard data:
{
"content": {"today": {...}, "week": {...}, "month": {...}},
"entity": {"today": {...}, "week": {...}, "month": {...}}
}
"""
try:
summary_data = get_summary_data()
return JSONResponse(content=summary_data)
except Exception as e: #pylint: disable=broad-except
return JSONResponse(content={"error": str(e)}, status_code=500)
@router.get("/{module}/{chart_id}")
def get_summary_chart(module: str, chart_id: str) -> JSONResponse:
"""
Handles GET requests to the summary route with a specific module and chart ID.
Args:
module (str): The module identifier (content or entity).
chart_id (str): The chart identifier (today, weekly, monthly).
Returns:
tuple: The result of the chart's process function and HTTP status code 200.
Raises:
ImportError: If the specified chart module cannot be imported.
AttributeError: If the imported module does not have a 'process' function.
Endpoint:
GET /<module>/<chart_id>
"""
try:
result = importlib.import_module(f"controllers.summary.{module}.{chart_id}").process()
return JSONResponse(content=result)
except ImportError as e:
return JSONResponse(content={"error": str(e)}, status_code=404)
except AttributeError as e:
return JSONResponse(content={"error": str(e)}, status_code=500)
@router.get("/{module}")
async def get_summary_module(module: str) -> JSONResponse:
"""
Handles GET requests to the summary route for a specific module.
Triggers the process for each chart under this module concurrently.
Args:
module (str): The module identifier (content or entity).
Returns:
dict: {"module": module, "charts": [chart1, chart2, ...]}
"""
try:
result = importlib.import_module("controllers.summary").process(module)
return JSONResponse(content=result)
except ImportError as e:
return JSONResponse(content={"error": str(e)}, status_code=404)
except Exception as e: #pylint: disable=broad-except
return JSONResponse(content={"error": str(e)}, status_code=500)
# @router.get("/{email}")
# async def get_user_document_stats(
# email: str = Path(..., description="User's email address")
# ) -> JSONResponse:
# """
# Get document statistics for a specific user.
# This endpoint counts the number of unique emails and files uploaded by the user.
# It groups documents by metadata.id to ensure unique document counting (not chunks).
# Args:
# email (str): The user's email address
# Returns:
# JSONResponse: A JSON response containing document counts:
# {
# "email": "[email protected]",
# "emails": 5,
# "files": 12,
# "total_documents": 17
# }
# Raises:
# HTTPException: 400 for invalid email, 500 for database errors
# """
# try:
# email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
# if not email or not re.match(email_pattern, email):
# raise HTTPException(
# status_code=400,
# detail="Invalid email format. Must be a valid email address."
# )
# # Get document counts from database
# result = knowledge_base.get_doc_count(email)
# # Add email to response
# result["email"] = email
# return JSONResponse(content=result, status_code=200)
# except ValueError as e:
# logger.error("Validation error for user %s: %s", email, str(e))
# raise HTTPException(status_code=400, detail=str(e)) # pylint: disable=raise-missing-from
# except Exception as e: # pylint: disable=broad-exception-caught
# logger.error("Database error for user %s: %s", email, str(e))
# raise HTTPException( # pylint: disable=raise-missing-from
# status_code=500,
# detail="Internal server error while retrieving document statistics."
# )