как остановить работу хендлера телеграмм бота
я пишу телеграмм бота и столкнулся с проблемой что когда вводишь команду /weather ты должен ввести название города и он через API выводит сводку погоды но как остановить этот хендлер я не знаю, эта функция не заканчивается, она работает после ввода команды /weather помогите остановить async def reaction(message: types.Message): что бы после ввода названия одного города функция заканчивалась вот код:
import requests
import datetime
from config import token1
from config import open_weather_token
from aiogram import Bot, types
from aiogram.dispatcher import Dispatcher
from aiogram.utils import executor
bot = Bot(token=token1)
dp = Dispatcher(bot)
@dp.message_handler(commands=['start'])
async def start_command(message: types.Message):
await message.reply("Привет, меня зовут Аркадий, что бы увидеть список команд введи /commands")
@dp.message_handler(commands=['commands'])
async def list_commands(message: types.Message):
await message.reply("Вот, держи список команд\n/start - преветсвующее сообщение\n/commands - список команд")
@dp.message_handler(commands=['weather'])
async def weather(message: types.Message):
await message.reply("Привет! Напиши мне название города и я пришлю сводку погоды!")
@dp.message_handler()
async def reaction(message: types.Message):
code_to_smile = {
"Clear": "Ясно \U00002600",
"Clouds": "Облачно \U00002601",
"Rain": "Дождь \U00002614",
"Drizzle": "Дождь \U00002614",
"Thunderstorm": "Гроза \U000026A1",
"Snow": "Снег \U0001F328",
"Mist": "Туман \U0001F32B"
}
try:
r = requests.get(
f"http://api.openweathermap.org/data/2.5/weather?q={message.text}&appid={open_weather_token}&units=metric"
)
data = r.json()
city = data["name"]
cur_weather = data["main"]["temp"]
weather_description = data["weather"][0]["main"]
if weather_description in code_to_smile:
wd = code_to_smile[weather_description]
else:
wd = "Посмотри в окно, не пойму что там за погода!"
humidity = data["main"]["humidity"]
pressure = data["main"]["pressure"]
wind = data["wind"]["speed"]
sunrise_timestamp = datetime.datetime.fromtimestamp(data["sys"]["sunrise"])
sunset_timestamp = datetime.datetime.fromtimestamp(data["sys"]["sunset"])
length_of_the_day = datetime.datetime.fromtimestamp(data["sys"]["sunset"]) - datetime.datetime.fromtimestamp(
data["sys"]["sunrise"])
await message.reply(f"***{datetime.datetime.now().strftime('%Y-%m-%d %H:%M')}***\n"
f"Погода в городе: {city}\nТемпература: {cur_weather}C° {wd}\n"
f"Влажность: {humidity}%\nДавление: {pressure} мм.рт.ст\nВетер: {wind} м/с\n"
f"Восход солнца: {sunrise_timestamp}\nЗакат солнца: {sunset_timestamp}\nПродолжительность дня: {length_of_the_day}\n"
f"***Хорошего дня!***"
)
except:
await message.reply("\U00002620 Проверьте название города \U00002620")
if __name__ == '__main__':
executor.start_polling(dp)
Ответы (1 шт):
Вам нужно использовать FSM для этого, вот примерно так это будет выглядеть.
import requests
import datetime
from aiogram.dispatcher.filters.state import StatesGroup, State
from config import token1
from config import open_weather_token
from aiogram import Bot, types
from aiogram.dispatcher import Dispatcher, FSMContext
from aiogram.utils import executor
bot = Bot(token=token1)
dp = Dispatcher(bot)
class StateWeather(StatesGroup):
weather = State()
@dp.message_handler(commands=['start'])
async def start_command(message: types.Message):
await message.reply("Привет, меня зовут Аркадий, что бы увидеть список команд введи /commands")
@dp.message_handler(commands=['commands'])
async def list_commands(message: types.Message):
await message.reply("Вот, держи список команд\n/start - преветсвующее сообщение\n/commands - список команд")
@dp.message_handler(commands=['weather'])
async def weather(message: types.Message):
await message.reply("Привет! Напиши мне название города и я пришлю сводку погоды!")
await StateWeather.weather.set()
@dp.message_handler(state=StateWeather.weather)
async def reaction(message: types.Message, state: FSMContext):
code_to_smile = {
"Clear": "Ясно \U00002600",
"Clouds": "Облачно \U00002601",
"Rain": "Дождь \U00002614",
"Drizzle": "Дождь \U00002614",
"Thunderstorm": "Гроза \U000026A1",
"Snow": "Снег \U0001F328",
"Mist": "Туман \U0001F32B"
}
try:
r = requests.get(
f"http://api.openweathermap.org/data/2.5/weather?q={message.text}&appid={open_weather_token}&units=metric"
)
data = r.json()
city = data["name"]
cur_weather = data["main"]["temp"]
weather_description = data["weather"][0]["main"]
if weather_description in code_to_smile:
wd = code_to_smile[weather_description]
else:
wd = "Посмотри в окно, не пойму что там за погода!"
humidity = data["main"]["humidity"]
pressure = data["main"]["pressure"]
wind = data["wind"]["speed"]
sunrise_timestamp = datetime.datetime.fromtimestamp(data["sys"]["sunrise"])
sunset_timestamp = datetime.datetime.fromtimestamp(data["sys"]["sunset"])
length_of_the_day = datetime.datetime.fromtimestamp(data["sys"]["sunset"]) - datetime.datetime.fromtimestamp(
data["sys"]["sunrise"])
await message.reply(f"***{datetime.datetime.now().strftime('%Y-%m-%d %H:%M')}***\n"
f"Погода в городе: {city}\nТемпература: {cur_weather}C° {wd}\n"
f"Влажность: {humidity}%\nДавление: {pressure} мм.рт.ст\nВетер: {wind} м/с\n"
f"Восход солнца: {sunrise_timestamp}\nЗакат солнца: {sunset_timestamp}\nПродолжительность дня: {length_of_the_day}\n"
f"***Хорошего дня!***"
)
await state.finish()
except:
await message.reply("\U00002620 Проверьте название города \U00002620")
if __name__ == '__main__':
executor.start_polling(dp)
Если кратко, то мы создали StateWeather который наследовали от StatesGroup и в нем создали определенный стейт, который вы можете назвать как хотите, ну как и название класса. Дальше в weather мы запустили стейт и добавили фильтр на ваш пустой хендлер, который срабатывает исключительно если запущено наше состояние (а также если то, что отправил юзер, является текстом). После верного срабатывания хендлера мы закрываем стейт.
Всё.