Files
PolyWeather/web/services/feedback_api.py
T

90 lines
2.7 KiB
Python
Raw Normal View History

2026-06-01 21:10:37 +08:00
"""User feedback API service functions."""
from __future__ import annotations
import json
from typing import Any, Dict
from fastapi import HTTPException, Request
from src.database.db_manager import DBManager
from web.core import UserFeedbackRequest
import web.routes as legacy_routes
_ALLOWED_FEEDBACK_CATEGORIES = {
"bug",
"data",
"idea",
"payment",
"account",
"other",
}
def _normalize_category(value: str) -> str:
normalized = str(value or "").strip().lower()
return normalized if normalized in _ALLOWED_FEEDBACK_CATEGORIES else "other"
def _bounded_context(context: Dict[str, Any]) -> Dict[str, Any]:
if not isinstance(context, dict):
return {}
try:
encoded = json.dumps(context, ensure_ascii=False, default=str)
except Exception:
return {"_error": "context_not_serializable"}
if len(encoded) <= 20_000:
return json.loads(encoded)
return {
"_truncated": True,
"raw_preview": encoded[:20_000],
}
def submit_user_feedback(request: Request, body: UserFeedbackRequest) -> Dict[str, Any]:
legacy_routes._bind_optional_supabase_identity(request)
message = str(body.message or "").strip()
if len(message) < 3:
raise HTTPException(status_code=400, detail="message is required")
user_id = str(getattr(request.state, "auth_user_id", "") or "").strip()
user_email = str(getattr(request.state, "auth_email", "") or "").strip()
contact = str(body.contact or "").strip() or user_email
feedback = DBManager().append_user_feedback(
category=_normalize_category(body.category),
message=message,
source=str(body.source or "terminal").strip().lower() or "terminal",
contact=contact,
user_id=user_id,
user_email=user_email,
context=_bounded_context(body.context),
)
return {"ok": True, "feedback": feedback}
2026-06-06 22:55:15 +08:00
def list_current_user_feedback(request: Request, *, limit: int = 20) -> Dict[str, Any]:
legacy_routes._bind_optional_supabase_identity(request)
user_id = str(getattr(request.state, "auth_user_id", "") or "").strip()
user_email = str(getattr(request.state, "auth_email", "") or "").strip()
if not user_id and not user_email:
raise HTTPException(status_code=401, detail="Supabase user required")
rows = DBManager().list_user_feedback(
limit=limit,
user_id=user_id,
user_email=user_email,
)
status_counts: Dict[str, int] = {}
for row in rows:
key = str(row.get("status") or "unknown")
status_counts[key] = status_counts.get(key, 0) + 1
return {
"feedback": rows,
"total": len(rows),
"status_counts": status_counts,
}