Files

119 lines
4.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import logging
from datetime import datetime
import aiohttp
from aiohttp_socks import ProxyConnector, ProxyType
from config import API_WEATHER, PROXY_ENABLED, PROXY_URL
from bot.bot import bot
logger = logging.getLogger(__name__)
def get_wind_direction(deg: float) -> str:
if deg >= 337.5 or deg < 22.5:
return "Север"
if deg < 67.5:
return "Северо-восток"
if deg < 112.5:
return "Восток"
if deg < 157.5:
return "Юго-восток"
if deg < 202.5:
return "Юг"
if deg < 247.5:
return "Юго-запад"
if deg < 292.5:
return "Запад"
return "Северо-запад"
def _get_connector():
if PROXY_ENABLED and PROXY_URL:
parsed = PROXY_URL.replace("socks5://", "").replace("socks5h://", "")
if "@" in parsed:
auth, host_port = parsed.split("@", 1)
username, password = auth.split(":", 1)
else:
username = None
password = None
host_port = parsed
host, port = host_port.rsplit(":", 1)
port = int(port)
return ProxyConnector(
proxy_type=ProxyType.SOCKS5,
host=host,
port=port,
username=username,
password=password,
)
return None
async def get_weather(message) -> None:
if len(message.text.split(maxsplit=1)) == 1:
await bot.send_message(message.chat.id, "Пожалуйста, укажите город.")
return
city = message.text.split(maxsplit=1)[1].strip()
url = "https://api.openweathermap.org/data/2.5/weather"
params = {"q": city, "appid": API_WEATHER, "units": "metric", "lang": "ru"}
timeout = aiohttp.ClientTimeout(total=30, sock_connect=15, sock_read=15)
connector = _get_connector()
try:
async with aiohttp.ClientSession(timeout=timeout, connector=connector) as session:
async with session.get(url, params=params) as response:
if response.status == 404:
await bot.send_message(message.chat.id, "Город не найден. Пожалуйста, уточните запрос.")
return
response.raise_for_status()
weather_data = await response.json()
weather_description = weather_data["weather"][0]["description"]
temperature = weather_data["main"]["temp"]
feels_like = weather_data["main"]["feels_like"]
temp_min = weather_data["main"]["temp_min"]
temp_max = weather_data["main"]["temp_max"]
humidity = weather_data["main"]["humidity"]
pressure = int(weather_data["main"]["pressure"] / 1.333)
wind_speed = weather_data["wind"]["speed"]
wind_deg = weather_data["wind"].get("deg", 0)
wind_direction = get_wind_direction(wind_deg)
rain_1h = weather_data.get("rain", {}).get("1h", 0)
clouds_all = weather_data["clouds"]["all"]
visibility = weather_data.get("visibility", 0)
sunrise_time = datetime.fromtimestamp(weather_data["sys"]["sunrise"]).strftime("%H:%M")
sunset_time = datetime.fromtimestamp(weather_data["sys"]["sunset"]).strftime("%H:%M")
weather_message = (
f"Погода в городе {city}:\n\n"
f"Описание: {weather_description}\n"
f"Температура: {temperature}°C (ощущается как {feels_like}°C)\n"
f"Минимальная температура: {temp_min}°C\n"
f"Максимальная температура: {temp_max}°C\n"
f"Влажность: {humidity}%\n"
f"Давление: {pressure} мм рт.ст\n"
f"Скорость ветра: {wind_speed} м/с, направление: {wind_direction}\n"
f"Осадки за последний час: {rain_1h} мм\n"
f"Облачность: {clouds_all}%\n"
f"Видимость: {visibility} м\n"
f"Восход: {sunrise_time}, закат: {sunset_time}"
)
await bot.send_message(message.chat.id, weather_message, parse_mode=None)
except aiohttp.ClientResponseError as exc:
logger.error("HTTP ошибка погоды: %s", exc)
await bot.send_message(message.chat.id, "При получении данных произошла ошибка, попробуйте еще раз.")
except aiohttp.ClientError as exc:
logger.error("Ошибка запроса погоды: %s", exc)
await bot.send_message(message.chat.id, "Не удалось связаться с погодным сервисом.")
except Exception as exc:
logger.exception("Неожиданная ошибка погоды: %s", exc)
await bot.send_message(message.chat.id, "Произошла ошибка при обработке погоды.")
finally:
if connector:
await connector.close()