| """ |
| Feedback endpoint — stores user feedback from the demo. |
| Simple JSON Lines file storage. No database needed. |
| """ |
| from __future__ import annotations |
|
|
| import json |
| import logging |
| from datetime import datetime, timezone |
| from pathlib import Path |
|
|
| from fastapi import APIRouter, Request |
| from pydantic import BaseModel, Field |
|
|
| logger = logging.getLogger(__name__) |
| router = APIRouter() |
|
|
| FEEDBACK_FILE = Path("/tmp/cds_feedback.jsonl") |
|
|
|
|
| class FeedbackSubmission(BaseModel): |
| message: str = Field(..., max_length=1000) |
| contact: str | None = Field(None, max_length=200) |
| page_url: str | None = None |
| user_agent: str | None = None |
|
|
|
|
| @router.post("/api/feedback") |
| async def submit_feedback(feedback: FeedbackSubmission, request: Request): |
| """Save user feedback to a JSONL file.""" |
| entry = { |
| "timestamp": datetime.now(timezone.utc).isoformat(), |
| "message": feedback.message, |
| "contact": feedback.contact, |
| "page_url": feedback.page_url, |
| "user_agent": feedback.user_agent, |
| "client_ip": request.client.host if request.client else None, |
| } |
|
|
| try: |
| with open(FEEDBACK_FILE, "a", encoding="utf-8") as f: |
| f.write(json.dumps(entry) + "\n") |
| logger.info(f"Feedback saved: {feedback.message[:50]}...") |
| except Exception as e: |
| logger.error(f"Failed to save feedback: {e}") |
| return {"status": "error", "message": "Failed to save feedback"} |
|
|
| return {"status": "ok", "message": "Thank you for your feedback!"} |
|
|
|
|
| @router.get("/api/feedback") |
| async def list_feedback(): |
| """List all feedback (for the developer). No auth — it's a demo.""" |
| if not FEEDBACK_FILE.exists(): |
| return {"feedback": [], "count": 0} |
|
|
| entries = [] |
| try: |
| with open(FEEDBACK_FILE, "r", encoding="utf-8") as f: |
| for line in f: |
| line = line.strip() |
| if line: |
| entries.append(json.loads(line)) |
| except Exception as e: |
| logger.error(f"Failed to read feedback: {e}") |
| return {"feedback": [], "count": 0, "error": str(e)} |
|
|
| return {"feedback": entries, "count": len(entries)} |
|
|