Как совместить работу aiogram и schedule на Тelegram bot
Хочу отправить каждый день в определенное время отправить сообщение подписчикам. Использую библиотеку schedule и aiogram
from aiogram import Bot, Dispatcher
from aiogram.types import *
from aiogram.utils import executor
import schedule
bot = Bot()
dp = Dispatcher(bot)
async def send_message():
await [email protected]_handler(commands=['start'])
async def start(message : Message):
await bot.send_photo(message.chat.id, open('static/img/qq.jpg', 'rb'))
await schedule.every().day.at("10:30").do(send_message)
while True:
schedule.run_pending()
time.sleep(1)
if __name__ == "__main__":
executor.start_polling(dp, skip_updates=True)
Ответы (3 шт):
async def send_message():
await [email protected]_handler(commands=['start'])
Что за конструкция такая "[email protected]"?
await schedule.every().day.at("10:30").do(send_message)
schedule.every() не является асинхронной функцией, которую нужно ожидать, хотя мы впринципе ничего не можем ожидать вне асинхронных функций.
while True:
schedule.run_pending()
time.sleep(1)
if __name__ == "__main__":
executor.start_polling(dp, skip_updates=True)
И тут находится венец всех ошибок, в вашем решении. В конце программы вы запускаете асинхронный event loop, который отслеживает события, но при этом чуть выше вы помещаете своего "бота" в синхронный бесконечный цикл, при этом еще и используя time.sleep(). schedule не может запустить выполнение вашей корутины. Вместо этого лучше использовать datetime как предложено здесь: https://stackoverflow.com/questions/51292027/how-to-schedule-a-task-in-asyncio-so-it-runs-at-a-certain-date А так же изучить как все это работает: https://geekbrains.ru/posts/python_threading_part1 https://proglib.io/p/python-asyncio/
Вместо schedule можно использовать её асинхронную версию - aioschedule.
Вот пример кода:
import asyncio
import aioschedule
async def noon_print():
print("It's noon!")
async def scheduler():
aioschedule.every().day.at("12:00").do(noon_print)
while True:
await aioschedule.run_pending()
await asyncio.sleep(1)
async def on_startup(x):
asyncio.create_task(scheduler())
if __name__ == '__main__':
executor.start_polling(dp, skip_updates=False, on_startup=on_startup)
executor.start_polling запускает функцию, указанную аргументом on_startup на старте. В этот момент у нас уже существует event_loop, что позволяет нам запустить планировщик "параллельной" (насколько асинхронный код может быть параллельным) задачей при помощи asyncio.create_task(scheduler()).
Можно использовать datetime
import datetime
from aiogram import Bot, Dispatcher, types, executor
import logging
from config import TOKEN
print(datetime.datetime.today())
print(datetime.datetime.now())
d1 = datetime.datetime.today()
print(d1)
d1 = d1+datetime.timedelta(days=1)
if d1.strftime("%M%S") == "0300":
print('lol')
print(d1.strftime("%M%S"))
logging.basicConfig(level=logging.INFO)
bot = Bot(TOKEN)
dp = Dispatcher(bot)
@dp.message_handler(commands=['start'])
async def bot_not_know(message: types.Message):
await bot.send_message(message.from_user.id, "Start!")
while True:
if d1.strftime("%M%S") == "1300": # в 13 минут 00 секунд будет сказано LOL
await message.answer('LOL')
@dp.message_handler()
async def bot_not_know(message: types.Message):
await bot.send_message(message.from_user.id, "Чел ты чё несёшь!?")
if __name__ == '__main__':
executor.start_polling(dp, skip_updates=True)