""" News data service for Tools domain. Fetches news headlines from the Qdrant volatile collection. """ from datetime import datetime from typing import Optional, Dict, Any, List from src.shared.logging import get_logger from src.shared.clients.qdrant_client import get_qdrant_client from src.domains.tools.news.schemas import ( NewsHeadline, NewsResponse, ) logger = get_logger(__name__) class NewsService: """ Service for fetching news data from Qdrant volatile collection. Retrieves news headlines for a specific user. """ def __init__(self): """Initialize news service with Qdrant client.""" self.qdrant = get_qdrant_client() def _parse_headlines(self, raw_data: Any) -> List[NewsHeadline]: """ Parse raw news data into list of NewsHeadline schemas. Handles various formats from different news sources. """ if not raw_data: return [] try: # Handle dict with nested headlines list headlines_list = raw_data if isinstance(raw_data, dict): headlines_list = raw_data.get("headlines") or raw_data.get("articles") or [] if not isinstance(headlines_list, list): return [] headlines = [] for item in headlines_list: if isinstance(item, dict): headlines.append(NewsHeadline( title=item.get("title", ""), description=item.get("description") or item.get("summary"), source=item.get("source") or item.get("provider"), url=item.get("url") or item.get("link"), )) elif isinstance(item, str): # Simple string headlines headlines.append(NewsHeadline(title=item)) return headlines except Exception as e: logger.warning(f"Failed to parse news headlines: {e}") return [] async def get_news(self, user: str = "default") -> NewsResponse: """ Get news headlines for a user. Fetches news from the user's volatile collection. Args: user: User identifier (default: 'default') Returns: NewsResponse with headlines """ logger.info(f"Fetching news data for user: {user}") # Get raw data from Qdrant news_records = await self.qdrant.get_by_namespace(user, "news") headlines = [] category = None sources = None if news_records: raw_data = news_records[0].get("raw_data", {}) headlines = self._parse_headlines(raw_data) if isinstance(raw_data, dict): category = raw_data.get("category") sources = raw_data.get("sources") return NewsResponse( headlines=headlines, category=category, sources=sources, updated_at=datetime.utcnow(), user=user, ) # Singleton instance _news_service: Optional[NewsService] = None def get_news_service() -> NewsService: """Get or create singleton news service instance.""" global _news_service if _news_service is None: _news_service = NewsService() return _news_service