Files
ALwrity/backend/api/podcast/handlers/trends.py
ajaysi 3f984e8d0c feat(podcast): add pre-estimate endpoint, enhance cost estimator with multi-model support, cleanup alpha pricing seeding
- Add POST /podcast/pre-estimate endpoint for cost estimation before analysis
- Enhance cost_estimator.py with multi-model support (gemini, audio, voice clone, image, video)
- Add detailed cost breakdown (llm, audio, media costs + per-phase breakdown)
- Remove redundant pricing seeding from init_alpha_subscription_tiers.py
- Add SSOT pricing via PricingService.initialize_default_pricing()
- Update TopicUrlInput tooltip to show estimate details
- Add debug logging for pricing seeding and pre-estimate
- Clean up verbose podcast mode debug logs in app.py
2026-05-06 15:29:12 +05:30

92 lines
3.7 KiB
Python

"""
Podcast Trends Handler
Endpoints for fetching Google Trends data relevant to podcast topics.
"""
from fastapi import APIRouter, Depends, HTTPException
from typing import Dict, Any, List, Optional
from pydantic import BaseModel, Field
from loguru import logger
from middleware.auth_middleware import get_current_user
router = APIRouter(prefix="/trends", tags=["Podcast Trends"])
class PodcastTrendsRequest(BaseModel):
keywords: List[str] = Field(..., min_length=1, max_length=5, description="1-5 keywords to analyze")
timeframe: str = Field(default="today 12-m", description="Timeframe: 'today 3-m', 'today 12-m', 'today 5-y', 'all'")
geo: str = Field(default="US", description="Country code: 'US', 'GB', 'IN', etc.")
source: str = Field(default="web", description="Data source: 'web' (Google), 'podcast' (YouTube)")
class PodcastTrendsResponse(BaseModel):
success: bool
data: Optional[Dict[str, Any]] = None
error: Optional[str] = None
@router.post("", response_model=PodcastTrendsResponse)
async def get_podcast_trends(
request: PodcastTrendsRequest,
current_user: Dict[str, Any] = Depends(get_current_user),
):
"""Fetch Google Trends data for podcast topic keywords."""
user_id = current_user.get("user_id") or current_user.get("id")
if not user_id:
raise HTTPException(status_code=401, detail="User ID not found")
try:
from services.research.trends import GoogleTrendsService
except (ImportError, RuntimeError) as e:
logger.error(f"[Podcast Trends] GoogleTrendsService unavailable: {e}")
raise HTTPException(
status_code=503,
detail="Google Trends service is currently unavailable. Please try again later."
)
try:
service = GoogleTrendsService()
# Map 'source' to 'gprop' - 'podcast' uses YouTube for video/podcast relevance
gprop_map = {"": "", "web": "", "podcast": "youtube", "news": "news", "images": "images", "shopping": "froogle"}
gprop = gprop_map.get(request.source, "")
result = await service.analyze_trends(
keywords=request.keywords,
timeframe=request.timeframe,
geo=request.geo,
gprop=gprop,
user_id=user_id,
)
has_error = result.get("error")
has_data = (
len(result.get("interest_over_time", [])) > 0
or len(result.get("interest_by_region", [])) > 0
or len(result.get("related_topics", {}).get("top", [])) > 0
or len(result.get("related_topics", {}).get("rising", [])) > 0
or len(result.get("related_queries", {}).get("top", [])) > 0
or len(result.get("related_queries", {}).get("rising", [])) > 0
)
# Return error if: has error OR no data (meaning blocked/empty)
if has_error and not has_data:
error_msg = result.get("error", "")
logger.warning(f"[Trends] No data or error: {error_msg[:100]}")
return PodcastTrendsResponse(success=False, data=result, error=error_msg or "No trends data available. Google may be blocking requests.")
# Even if no error but empty data - return error
if not has_data:
logger.warning("[Trends] Empty data returned")
return PodcastTrendsResponse(success=False, data=result, error="No trends data available. Please try different keywords.")
return PodcastTrendsResponse(success=True, data=result)
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
logger.error(f"[Podcast Trends] Error fetching trends for {request.keywords}: {e}")
raise HTTPException(
status_code=500,
detail=f"Failed to fetch trends data: {str(e)}"
)