Spaces:
Running
Running
| """Author RAG β Support Service. | |
| Business logic for admin support: publish-help request orchestration. | |
| """ | |
| from datetime import datetime, timezone | |
| import structlog | |
| from fastapi import HTTPException | |
| from sqlalchemy.ext.asyncio import AsyncSession | |
| from app.config import get_settings | |
| from app.models.user import User | |
| from app.repositories.book_repo import BookRepository | |
| from app.schemas.admin import ContactRequest, PublishHelpRequest | |
| from app.services.book_url_scraper import PLATFORM_DISPLAY | |
| from app.services.platform_presence import SCORED_PLATFORMS | |
| logger = structlog.get_logger(__name__) | |
| _PLATFORM_NAMES = { | |
| p["platform_id"]: p["display_name"] for p in SCORED_PLATFORMS | |
| } | |
| class SupportService: | |
| """Orchestrates publish-help requests and support config.""" | |
| def __init__(self, db: AsyncSession) -> None: | |
| self._db = db | |
| self._books = BookRepository(db) | |
| def get_config() -> dict: | |
| """Return support contact info for the admin UI.""" | |
| cfg = get_settings() | |
| return { | |
| "support_email": str(cfg.SUPPORT_EMAIL) if cfg.SUPPORT_EMAIL else None, | |
| } | |
| async def queue_publish_help_request( | |
| self, user: User, body: PublishHelpRequest | |
| ) -> dict: | |
| """Validate, build payload, and queue publish-help email to support.""" | |
| cfg = get_settings() | |
| if not cfg.SUPPORT_EMAIL: | |
| raise HTTPException(503, "Support email is not configured") | |
| book_meta = await self._resolve_book_meta(user.id, body) | |
| platform_names = [ | |
| _PLATFORM_NAMES.get(pid, PLATFORM_DISPLAY.get(pid, pid.replace("_", " ").title())) | |
| for pid in body.platform_ids | |
| ] | |
| payload = { | |
| "author_name": user.full_name or user.email, | |
| "author_email": user.email, | |
| "book_title": body.book_title, | |
| "book_id": body.book_id, | |
| "isbn": (book_meta or {}).get("isbn"), | |
| "book_author": (book_meta or {}).get("book_author"), | |
| "source_url": body.source_url or (book_meta or {}).get("source_url"), | |
| "platform_names": platform_names, | |
| "message": body.message, | |
| "submitted_at": datetime.now(timezone.utc).isoformat(), | |
| } | |
| from app.tasks.email_task import send_publish_help_request as send_publish_help_task | |
| send_publish_help_task.delay(payload) | |
| logger.info( | |
| "Publish help request queued", | |
| author_id=user.id, | |
| book_id=body.book_id, | |
| platforms=body.platform_ids, | |
| ) | |
| return {"message": "Request received β we'll reply within 24 hours"} | |
| async def queue_contact_request( | |
| self, user: User, body: ContactRequest | |
| ) -> dict: | |
| """Validate and queue a general contact email to support.""" | |
| cfg = get_settings() | |
| if not cfg.SUPPORT_EMAIL: | |
| raise HTTPException(503, "Support email is not configured") | |
| category_labels = { | |
| "general": "General", | |
| "billing": "Billing", | |
| "technical": "Technical", | |
| "publishing": "Publishing", | |
| } | |
| payload = { | |
| "author_name": user.full_name or user.email, | |
| "author_email": user.email, | |
| "category": category_labels.get(body.category, body.category), | |
| "message": body.message, | |
| "submitted_at": datetime.now(timezone.utc).isoformat(), | |
| } | |
| from app.tasks.email_task import send_contact_request as send_contact_task | |
| send_contact_task.delay(payload) | |
| logger.info("Contact request queued", author_id=user.id, category=body.category) | |
| return {"message": "Message sent β we'll reply within 24 hours"} | |
| async def _resolve_book_meta( | |
| self, author_id: str, body: PublishHelpRequest | |
| ) -> dict | None: | |
| """Load ISBN/author/source_url from DB when book_id is provided.""" | |
| if not body.book_id: | |
| return None | |
| book = await self._books.get_by_id(body.book_id) | |
| if not book or book.author_id != author_id: | |
| raise HTTPException(404, "Book not found") | |
| return { | |
| "isbn": book.isbn, | |
| "source_url": book.source_url or body.source_url, | |
| "book_author": book.book_author, | |
| } | |