Фикс произношения дат и температуры + wheather -лишние файлы
This commit is contained in:
144
app/features/weather.py
Normal file
144
app/features/weather.py
Normal file
@@ -0,0 +1,144 @@
|
||||
"""
|
||||
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 "Не удалось получить полные данные о погоде."
|
||||
Reference in New Issue
Block a user