From 5dc6c54bf64ad7aba210bc7d1ba5f4e415731500 Mon Sep 17 00:00:00 2001 From: deadzilla Date: Sun, 24 May 2026 22:55:49 +0500 Subject: [PATCH] chore: migrate pogoda to wttr.in, fix bot stop, add on_command_error --- bot.py | 31 +++++++------ commands/pogoda.py | 105 +++++++++++++++++++++------------------------ 2 files changed, 68 insertions(+), 68 deletions(-) diff --git a/bot.py b/bot.py index 35dce0c..e8cb953 100644 --- a/bot.py +++ b/bot.py @@ -5,6 +5,8 @@ import threading import discord from discord.ext import commands +from discord.ext.commands import CommandNotFound +from discord.ext.commands import CommandNotFound from dotenv import load_dotenv from commands import ALL_COMMANDS @@ -28,6 +30,20 @@ async def on_ready(): print(f" Загружен: {cog}") +@bot.event +async def on_command_error(ctx, error): + if isinstance(error, CommandNotFound): + return + print(f"Ошибка команды: {error}") + + +@bot.event +async def on_command_error(ctx, error): + if isinstance(error, CommandNotFound): + return + print(f"Ошибка команды: {error}") + + @bot.command(name="msg") async def msg(ctx, *, text: str): """Повторяет текст после !msg""" @@ -41,19 +57,13 @@ def console_input(): if cmd == "stop": print("\nОстановка бота...") stop_event.set() - try: - bot.loop.stop() - except (AttributeError, RuntimeError): - pass + asyncio.run_coroutine_threadsafe(bot.close(), bot.loop).result() break elif cmd: print(f"Неизвестная команда: {cmd}") except EOFError: stop_event.set() - try: - bot.loop.stop() - except (AttributeError, RuntimeError): - pass + asyncio.run_coroutine_threadsafe(bot.close(), bot.loop).result() break @@ -71,9 +81,6 @@ if __name__ == "__main__": bot.run(token) except KeyboardInterrupt: print("\nОстановка бота...") - try: - bot.loop.stop() - except (AttributeError, RuntimeError): - pass stop_event.set() + asyncio.run_coroutine_threadsafe(bot.close(), bot.loop).result() sys.exit(0) diff --git a/commands/pogoda.py b/commands/pogoda.py index bde8bac..9b9087c 100644 --- a/commands/pogoda.py +++ b/commands/pogoda.py @@ -7,81 +7,74 @@ class Pogoda(commands.Cog): """Команда !pogoda — прогноз погоды для Магнитогорска""" def __init__(self): - self.api_url = "https://api.open-meteo.com/v1/forecast" - self.lat = 53.41 - self.lon = 59.06 + self.api_url = "https://wttr.in/Magnitogorsk?format=j1&lang=ru" @commands.command(name="pogoda") async def pogoda(self, ctx): - params = { - "latitude": self.lat, - "longitude": self.lon, - "current": "temperature_2m,weather_code,relative_humidity_2m,wind_speed_10m,pressure_msl", - "timezone": "Asia/Yekaterinburg", - } - try: - response = requests.get(self.api_url, params=params, timeout=10) + response = requests.get(self.api_url, timeout=10) response.raise_for_status() data = response.json() except requests.RequestException as e: await ctx.send(f"Ошибка при получении данных: {e}") return - current = data.get("current", {}) + current = data.get("current_condition", [{}])[0] if not current: await ctx.send("Не удалось получить данные о погоде.") return - temp = current.get("temperature_2m", "—") - weather_code = current.get("weather_code", "—") - humidity = current.get("relative_humidity_2m", "—") - wind = current.get("wind_speed_10m", "—") - pressure = current.get("pressure_msl", "—") + temp = current.get("temp_C", "—") + feels_like = current.get("FeelsLikeC", "—") + description = self._translate_weather(current.get("weatherDesc", [{}])[0].get("value", "—")) + humidity = current.get("humidity", "—") + wind_kmh = current.get("windspeedKmph", "—") + wind = round(int(wind_kmh) / 3.6, 1) if wind_kmh != "—" else "—" + pressure_mb = current.get("pressure", "—") - description = self._get_weather_description(weather_code) - pressure_mm = self._pressure_to_mmhg(pressure) + pressure_mm = self._pressure_to_mmhg(pressure_mb) await ctx.send( - f"🌡 Температура: {temp}°C\n" - f"📝 Описание: {description}\n" - f"💧 Влажность: {humidity}%\n" - f"💨 Ветер: {wind} км/ч\n" - f"🌍 Давление: {pressure_mm} мм рт. ст." + f"[TEMP] Температура: {temp}°C (ощущается как {feels_like}°C)\n" + f"[DESC] Описание: {description}\n" + f"[HUMID] Влажность: {humidity}%\n" + f"[WIND] Ветер: {wind} м/с\n" + f"[PRESS] Давление: {pressure_mm} мм рт. ст." ) - def _get_weather_description(self, code): - descriptions = { - 0: "Ясно", - 1: "Преимущественно ясно", - 2: "Переменная облачность", - 3: "Пасмурно", - 45: "Туман", - 48: "Изморозь", - 51: "Лёгкая морось", - 53: "Морось", - 55: "Сильная морось", - 61: "Небольшой дождь", - 63: "Дождь", - 65: "Сильный дождь", - 66: "Ледяной дождь", - 67: "Сильный ледяной дождь", - 71: "Небольшой снег", - 73: "Снег", - 75: "Сильный снег", - 77: "Снежная крупа", - 80: "Небольшой ливень", - 81: "Ливень", - 82: "Сильный ливень", - 85: "Небольшой снегопад", - 86: "Сильный снегопад", - 95: "Гроза", - 96: "Гроза с градом", - 99: "Сильная гроза с градом", + def _translate_weather(self, en): + mapping = { + "Sunny": "Ясно", + "Clear": "Ясно", + "Partly cloudy": "Переменная облачность", + "Cloudy": "Облачно", + "Overcast": "Пасмурно", + "Mist": "Туман", + "Fog": "Туман", + "Patchy rain nearby": "Местами дождь", + "Light rain": "Небольшой дождь", + "Moderate rain": "Умеренный дождь", + "Heavy rain": "Сильный дождь", + "Patchy snow nearby": "Местами снег", + "Light snow": "Небольшой снег", + "Heavy snow": "Сильный снег", + "Patchy sleet nearby": "Местами слякоть", + "Blowing snow": "Метель", + "Thundery outbreaks in nearby": "Гроза вблизи", + "Moderate or heavy snow in area": "Снег", + "Moderate or heavy rain in area": "Дождь", + "Moderate or heavy freezing rain in area": "Ледяной дождь", + "Moderate or heavy sleet in area": "Слякоть", + "Ice pellets": "Ледяные кристаллы", + "Haze": "Дымка", + "Foggy": "Туманно", } - return descriptions.get(code, "Неизвестно") + for key, value in mapping.items(): + if key.lower() in en.lower(): + return value + return en - def _pressure_to_mmhg(self, hpa): - if hpa == "—": + def _pressure_to_mmhg(self, mb): + if mb == "—": return "—" - return round(hpa * 0.750062, 1) + return round(int(mb) * 0.750062, 1)