""" Google Trends adapter (experimental, feature-flagged). Disabled by default; enable via GOOGLE_TRENDS_ENABLED=true env var. """ import logging from datetime import datetime, timezone from typing import List from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select, and_ from app.core.config import settings from app.models.overlay_registry import ThemeTopicMap from app.models.overlay_raw_event import OverlayTrendObservation logger = logging.getLogger(__name__) class GoogleTrendsAdapter: """Collect Google Trends data (experimental, disabled by default).""" @property def enabled(self) -> bool: return getattr(settings, "GOOGLE_TRENDS_ENABLED", False) async def collect(self, db: AsyncSession) -> int: """ Collect Google Trends interest data for active topics. Returns 0 if feature flag is disabled or pytrends is not installed. Returns number of new records inserted. """ if not self.enabled: logger.debug("Google Trends adapter: feature flag disabled, skipping") return 0 try: from pytrends.request import TrendReq except ImportError: logger.warning("pytrends not installed; Google Trends adapter inactive") return 0 result = await db.execute( select(ThemeTopicMap).where(ThemeTopicMap.active == True) ) topics = result.scalars().all() if not topics: return 0 inserted = 0 try: pytrends = TrendReq(hl="en-US", tz=360) # pytrends limits to 5 keywords at a time kw_list = [t.topic_label for t in topics[:5]] pytrends.build_payload(kw_list, timeframe="now 7-d", geo="US") interest_df = pytrends.interest_over_time() except Exception as e: logger.error(f"Google Trends API error: {e}") return 0 for topic in topics: if topic.topic_label not in interest_df.columns: continue series = interest_df[topic.topic_label] for ts, val in series.items(): observed_at = ts.to_pydatetime().replace(tzinfo=timezone.utc) # Check duplicate existing = await db.execute( select(OverlayTrendObservation.id).where( and_( OverlayTrendObservation.topic_id == topic.topic_id, OverlayTrendObservation.observed_at == observed_at, OverlayTrendObservation.geography == "US", ) ) ) if existing.first(): continue record = OverlayTrendObservation( topic_id=topic.topic_id, observed_at=observed_at, geography="US", interest_value=int(val), ) db.add(record) inserted += 1 if inserted: await db.commit() logger.info(f"Google Trends: inserted {inserted} observations") return inserted