@NoKit

Как реализовать отправку уведомлений ботом при соблюдении условий?

Делаю бота, хочу реализовать отправку уведомлений в ЛС сообщения пользователю, когда его подписка истекает.
В БД есть дата окончания подписки, сравниваю ее с текущей датой и отправляю сообщение, если подписка истечет через n дней

Бота пишу на aiogram и asynsio. Основной код с запуском бота:
async def main():

    # Настройка логирования в stdout
    logging.basicConfig(
        level=logging.INFO,
        format="%(asctime)s - %(levelname)s - %(name)s - %(message)s",
    )
    logger.error("Starting bot")

    # Объявление и инициализация объектов бота и диспетчера
    bot = Bot(token="*******")
    dp = Dispatcher(bot, storage=MemoryStorage())

    sql = DateBase()

    # Регистрация хэндлеров
    register_handlers_choose(dp)
    register_handlers_common(dp)

    # Установка команд бота
    #await set_commands(bot)

    # Запуск поллинга
    await dp.start_polling()

    await sql.run_check()


if __name__ == '__main__':
    asyncio.run(main())


Код работы с БД:
import sqlite3 as sl
import schedule
import time

class DateBase():


    def __init__(self):
        self.db = sl.connect('users.db')
        self.cur = self.db.cursor()
        # Создание бд с проверкой на наличие
        with self.db:
            self.db.execute("""
                        CREATE TABLE IF NOT EXISTS users (
                            id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
                            name TEXT,
                            sub INTEGER,
                            until TEXT 
                        );
                    """)
            self.db.commit()



    def check_sub_job(self):
        print("Проверка")
     

    async def run_check(self):
        schedule.every(5).seconds.do(self.check_sub_job)
        while True:
            schedule.run_pending()
            time.sleep(1)


Когда запускаю бота, начинается бесконечная отправка сообщения Проверка, а сам бот на команды не реагирует. Предполагаю корутина с отправкой сообщения блокирует корутину с запуском поллинга.

Можете подсказать как исправить или может есть более легкий путь реализовать проверку БД с периодом и отправкой уведомлений пользователям бота?
  • Вопрос задан
  • 126 просмотров
Решения вопроса 1
Vindicar
@Vindicar
RTFM!
Еще один человек бросился писать ботов, не озаботившись изучить азы асинхронного программирования.

Если очень коротко: пока твой код делает что угодно кроме await-вызова, остальной бот стоит.
То есть:
time.sleep(10) - весь бот стоит и спит 10 секунд
await asyncio.sleep(10) - текущая корутина стоит и спит 10 секунд, но в это время могут выполняться другие корутины. Например, реакция на внешние события.

Что это тут у нас?
while True:
            schedule.run_pending()
            time.sleep(1)

Мало того, что бесконечный цикл, так ещё и ожидание делаешь через time.sleep(), который про асинхронность не знает.

И далее. А на кой овощ тебе вообще использовать schedule, если тебе требуется простое периодическое действие? Особенно с учётом того, что schedule - это тоже синхронная библиотека. Т.е. ты из асихронного бота вызывает синхронный код schedule, а потом оттуда будешь вызывать асинхронные методы отправки сообщений? Хороший способ усложнить себе жизнь!

async def check_if_notifications_are_needed(self):
    pass
#а ниже будет что-то типа
async def run_check(self):
    while True:
        await self.check_if_notifications_are_needed()
        await asyncio.sleep(3600) #серьезно, зачем проверять каждые 5 секунд если достаточно раз в час?
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы