import requests import logging from datetime import datetime, timezone from django.conf import settings logger = logging.getLogger(__name__) class CoinGeckoFetcher: """Fetches Bitcoin data from CoinGecko API.""" def __init__(self): self.base_url = "https://api.coingecko.com/api/v3" self.session = requests.Session() self.session.headers.update({ 'User-Agent': 'BitcoinMonitor/1.0', 'Accept': 'application/json', }) # Optional API key for higher rate limits api_key = settings.BITCOIN_MONITOR.get('COINGECKO_API_KEY') if api_key: self.session.headers['x-cg-pro-api-key'] = api_key def fetch_current_price(self): """Fetch current Bitcoin price.""" try: url = f"{self.base_url}/simple/price" params = { 'ids': 'bitcoin', 'vs_currencies': 'usd', 'include_market_cap': 'true', 'include_24hr_vol': 'true', 'include_last_updated_at': 'true', } logger.debug(f"Fetching current price from {url}") response = self.session.get(url, params=params, timeout=10) response.raise_for_status() data = response.json() if 'bitcoin' not in data: logger.error("Bitcoin data not found in response") return None btc_data = data['bitcoin'] return { 'timestamp': datetime.fromtimestamp( btc_data.get('last_updated_at', datetime.now(timezone.utc).timestamp()), timezone.utc ), 'price_usd': btc_data['usd'], 'market_cap': btc_data.get('usd_market_cap'), 'volume': btc_data.get('usd_24h_vol'), } except requests.exceptions.RequestException as e: logger.error(f"Request error fetching current price: {e}") return None except Exception as e: logger.error(f"Error fetching current price: {e}") return None def fetch_price_history(self, days=30): """Fetch historical price data (for future use).""" try: url = f"{self.base_url}/coins/bitcoin/market_chart" params = { 'vs_currency': 'usd', 'days': days, 'interval': 'daily', } logger.debug(f"Fetching {days} days of price history") response = self.session.get(url, params=params, timeout=30) response.raise_for_status() data = response.json() prices = [] for point in data.get('prices', []): prices.append({ 'timestamp': datetime.fromtimestamp(point[0] / 1000, timezone.utc), 'price': point[1], }) return { 'prices': prices, 'total_points': len(prices), } except requests.exceptions.RequestException as e: logger.error(f"Request error fetching price history: {e}") return None except Exception as e: logger.error(f"Error fetching price history: {e}") return None