"""CNN Fear & Greed Index collector.""" import logging from dataclasses import dataclass import aiohttp from news_collector.collectors.base import BaseCollector logger = logging.getLogger(__name__) FEAR_GREED_URL = "https://production.dataviz.cnn.io/index/fearandgreed/graphdata" @dataclass class FearGreedResult: fear_greed: int fear_greed_label: str class FearGreedCollector(BaseCollector): name = "fear_greed" poll_interval = 3600 # 1 hour async def is_available(self) -> bool: return True async def _fetch_index(self) -> dict | None: headers = {"User-Agent": "Mozilla/5.0"} try: async with aiohttp.ClientSession() as session: async with session.get( FEAR_GREED_URL, headers=headers, timeout=aiohttp.ClientTimeout(total=10) ) as resp: if resp.status != 200: return None return await resp.json() except Exception: return None def _classify(self, score: int) -> str: if score <= 20: return "Extreme Fear" if score <= 40: return "Fear" if score <= 60: return "Neutral" if score <= 80: return "Greed" return "Extreme Greed" async def collect(self) -> FearGreedResult | None: data = await self._fetch_index() if data is None: return None try: fg = data["fear_and_greed"] score = int(fg["score"]) label = fg.get("rating", self._classify(score)) return FearGreedResult(fear_greed=score, fear_greed_label=label) except (KeyError, ValueError, TypeError): return None