Загрузить файлы в «/»
This commit is contained in:
parent
6a6f7efe00
commit
7ecb1d4288
1 changed files with 122 additions and 0 deletions
122
bot-tg.py
Normal file
122
bot-tg.py
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
import logging
|
||||||
|
from logging.handlers import RotatingFileHandler
|
||||||
|
from aiogram import Bot, Dispatcher, types
|
||||||
|
from aiogram.filters import Command
|
||||||
|
from aiogram.utils.keyboard import ReplyKeyboardBuilder
|
||||||
|
import requests
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
# настройка логов
|
||||||
|
logger = logging.getLogger()
|
||||||
|
logger.setLevel(logging.DEBUG) # Включаем детальное логирование
|
||||||
|
|
||||||
|
formatter = logging.Formatter(
|
||||||
|
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||||
|
)
|
||||||
|
|
||||||
|
# логирование в файл, максимум 5мб по 3 бэкапа
|
||||||
|
file_handler = RotatingFileHandler(
|
||||||
|
'weather_bot.log',
|
||||||
|
maxBytes=5*1024*1024,
|
||||||
|
backupCount=3,
|
||||||
|
encoding='utf-8'
|
||||||
|
)
|
||||||
|
file_handler.setFormatter(formatter)
|
||||||
|
|
||||||
|
# вывод в консоль
|
||||||
|
console_handler = logging.StreamHandler()
|
||||||
|
console_handler.setFormatter(formatter)
|
||||||
|
|
||||||
|
logger.addHandler(file_handler)
|
||||||
|
logger.addHandler(console_handler)
|
||||||
|
|
||||||
|
# конфиг
|
||||||
|
try:
|
||||||
|
from config import BOT_TOKEN, WEATHER_API_KEY
|
||||||
|
except ImportError:
|
||||||
|
logging.critical("Ошибка: Создайте файл config.py с BOT_TOKEN и WEATHER_API_KEY!")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
# инициализация бота
|
||||||
|
bot = Bot(token=BOT_TOKEN)
|
||||||
|
dp = Dispatcher()
|
||||||
|
|
||||||
|
# клавиатура
|
||||||
|
builder = ReplyKeyboardBuilder()
|
||||||
|
builder.button(text="Узнать погоду")
|
||||||
|
builder.button(text="Помощь")
|
||||||
|
keyboard = builder.as_markup(resize_keyboard=True)
|
||||||
|
|
||||||
|
# обработка команд
|
||||||
|
@dp.message(Command("start", "help"))
|
||||||
|
async def cmd_start(message: types.Message):
|
||||||
|
logging.info(f"Новый пользователь: {message.from_user.id}")
|
||||||
|
await message.answer(
|
||||||
|
"Бот Погоды\n\n"
|
||||||
|
"Отправьте мне название города, и я пришлю текущую погоду.\n"
|
||||||
|
"Или нажмите кнопку ниже:",
|
||||||
|
reply_markup=keyboard
|
||||||
|
)
|
||||||
|
|
||||||
|
@dp.message(lambda message: message.text in ["Узнать погоду", "ℹ️ Помощь"])
|
||||||
|
async def button_handler(message: types.Message):
|
||||||
|
if message.text == "Узнать погоду":
|
||||||
|
await message.answer("Введите название города:")
|
||||||
|
else:
|
||||||
|
await cmd_start(message)
|
||||||
|
|
||||||
|
@dp.message()
|
||||||
|
async def get_weather(message: types.Message):
|
||||||
|
city = message.text.strip()
|
||||||
|
if not city:
|
||||||
|
return
|
||||||
|
|
||||||
|
logging.info(f"Запрос погоды для: {city} (от {message.from_user.id})")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Запрос к API
|
||||||
|
url = f"https://api.openweathermap.org/data/2.5/weather?q={city}&appid={WEATHER_API_KEY}&units=metric&lang=ru"
|
||||||
|
response = requests.get(url, timeout=10)
|
||||||
|
|
||||||
|
logging.debug(f"API Response: {response.status_code} {response.text[:200]}...")
|
||||||
|
|
||||||
|
if response.status_code != 200:
|
||||||
|
error_msg = response.json().get('message', 'Unknown error')
|
||||||
|
logging.error(f"API Error for {city}: {response.status_code} - {error_msg}")
|
||||||
|
await message.answer(f"❌ Ошибка: {error_msg.capitalize()}")
|
||||||
|
return
|
||||||
|
|
||||||
|
data = response.json()
|
||||||
|
|
||||||
|
# Формирование ответа
|
||||||
|
weather_report = (
|
||||||
|
f"Город: {data['name']}\n"
|
||||||
|
f"Температура: {data['main']['temp']:.1f}°C\n"
|
||||||
|
f"Ощущается как: {data['main']['feels_like']:.1f}°C\n"
|
||||||
|
f"Ветер: {data['wind']['speed']} м/с\n"
|
||||||
|
f"Погода: {data['weather'][0]['description'].capitalize()}\n"
|
||||||
|
f"Влажность: {data['main']['humidity']}%"
|
||||||
|
)
|
||||||
|
|
||||||
|
logging.info(f"Успешный ответ для {city}")
|
||||||
|
await message.answer(weather_report)
|
||||||
|
|
||||||
|
except requests.exceptions.Timeout:
|
||||||
|
logging.error(f"Таймаут запроса для {city}")
|
||||||
|
await message.answer("Сервер погоды не отвечает. Попробуйте позже.")
|
||||||
|
except Exception as e:
|
||||||
|
logging.exception(f"Ошибка для {city}:")
|
||||||
|
await message.answer("⚠️ Произошла внутренняя ошибка. Попробуйте другой город.")
|
||||||
|
|
||||||
|
# запуск бота
|
||||||
|
async def main():
|
||||||
|
logging.info("Starting bot...")
|
||||||
|
await dp.start_polling(bot)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
asyncio.run(main())
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
logging.info("Bot stopped by user")
|
||||||
|
except Exception as e:
|
||||||
|
logging.critical(f"Fatal error: {e}")
|
Loading…
Add table
Reference in a new issue