""" Weather feature module. Fetches weather data from Open-Meteo API. """ import requests from datetime import datetime from ..core.config import WEATHER_LAT, WEATHER_LON, WEATHER_CITY def get_wmo_description(code: int) -> str: """Decodes WMO weather code to Russian description.""" codes = { 0: "ясно", 1: "преимущественно ясно", 2: "переменная облачность", 3: "пасмурно", 45: "туман", 48: "изморозь", 51: "легкая морось", 53: "умеренная морось", 55: "плотная морось", 56: "ледяная морось", 57: "плотная ледяная морось", 61: "слабый дождь", 63: "умеренный дождь", 65: "сильный дождь", 66: "ледяной дождь", 67: "сильный ледяной дождь", 71: "слабый снег", 73: "снегопад", 75: "сильный снегопад", 77: "снежные зерна", 80: "слабый ливень", 81: "умеренный ливень", 82: "сильный ливень", 85: "слабый снегопад", 86: "сильный снегопад", 95: "гроза", 96: "гроза с градом", 99: "сильная гроза с градом" } return codes.get(code, "осадки") def get_weather_report() -> str: """ Fetches detailed weather report. Structure: 1. Current temp and precipitation. 2. Today's min/max temp. 3. Next 4 hours forecast (temp + precipitation). """ if not all([WEATHER_LAT, WEATHER_LON, WEATHER_CITY]): return "Настройки погоды не найдены. Проверьте конфигурацию." url = "https://api.open-meteo.com/v1/forecast" params = { "latitude": WEATHER_LAT, "longitude": WEATHER_LON, "current": "temperature_2m,precipitation,weather_code", "hourly": "temperature_2m,precipitation,weather_code", "daily": "temperature_2m_max,temperature_2m_min", "timezone": "auto", "forecast_days": 2 } try: response = requests.get(url, params=params, timeout=5) response.raise_for_status() data = response.json() # --- 1. Current Weather --- curr = data["current"] temp_now = round(curr["temperature_2m"]) precip_now = curr["precipitation"] code_now = curr["weather_code"] desc_now = get_wmo_description(code_now) report = f"Сейчас в городе {WEATHER_CITY} {temp_now} градусов, {desc_now}." if precip_now > 0: report += f" Выпало {precip_now} миллиметров осадков." # --- 2. Today's Range --- # daily arrays usually start from today [0] daily = data["daily"] t_max = round(daily["temperature_2m_max"][0]) t_min = round(daily["temperature_2m_min"][0]) report += f" Сегодня температура будет от {t_min} до {t_max} градусов." # --- 3. Forecast Next 4 Hours --- current_hour = datetime.now().hour hourly_temps = data["hourly"]["temperature_2m"] hourly_precip = data["hourly"]["precipitation"] hourly_codes = data["hourly"]["weather_code"] # Start from next hour start_idx = current_hour + 1 end_idx = min(start_idx + 4, len(hourly_temps)) next_temps = hourly_temps[start_idx:end_idx] next_precip = hourly_precip[start_idx:end_idx] next_codes = hourly_codes[start_idx:end_idx] if next_temps: report += " Прогноз на ближайшие 4 часа: " # Group by roughly similar weather to avoid repetition? # Or just list them simply. # "В 14:00 -5, ясно. В 15:00 -5, снег." -> a bit verbose. # Simplified: "Температура около -5, возможен слабый снег." # Let's verify if weather changes significantly. # If consistent, summarize. If not, list. # Simple approach for TTS: avg_temp = round(sum(next_temps) / len(next_temps)) # Check if any precipitation is expected will_precip = any(p > 0 for p in next_precip) unique_codes = set(next_codes) # Determine dominant weather description if len(unique_codes) == 1: weather_desc = get_wmo_description(list(unique_codes)[0]) else: # Priority to precipitation codes precip_codes = [c for c in unique_codes if c > 3] # >3 implies not clear/cloudy if precip_codes: weather_desc = get_wmo_description(max(precip_codes)) # Take the most severe else: weather_desc = "переменная облачность" report += f"температура около {avg_temp} градусов, {weather_desc}." if will_precip: report += " Ожидаются осадки." else: report += " Без существенных осадков." return report except Exception as e: print(f"❌ Ошибка получения погоды: {e}") return "Не удалось получить полные данные о погоде."