N
N
NoKit2021-10-13 15:56:07
Python
NoKit, 2021-10-13 15:56:07

How to implement sending notifications by the bot when the conditions are met?

I'm making a bot, I want to send notifications to the LAN of a message to the user when his subscription expires.
There is a subscription expiration date in the database, I compare it with the current date and send a message if the subscription expires in n days

. I write to the bot on aiogram and asyncio. The main code with the launch of the bot:

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())


Code for working with the database:
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)


When I launch the bot, an endless sending of the Check message begins, and the bot itself does not respond to commands. I assume a coroutine with sending a message blocks a coroutine with the launch of polling.

Can you tell me how to fix it or maybe there is an easier way to implement a database check with a period and sending notifications to bot users?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
V
Vindicar, 2021-10-13
@NoKit

Another person rushed to write bots, not bothering to learn the basics of asynchronous programming.
In short, as long as your code does anything other than await, the rest of the bot is worth .
That is:
time.sleep(10) - the whole bot stands and sleeps for 10 seconds
await asyncio.sleep(10) - the current coroutine stands and sleeps for 10 seconds, but other coroutines can be executed at this time. For example, reaction to external events.
What do we have here?

while True:
            schedule.run_pending()
            time.sleep(1)

Not only is it an infinite loop, but you also do the waiting through time.sleep(), which does not know about asynchrony.
And further. And what vegetable do you even use schedule for, if you need a simple periodic action? Especially considering that schedule is also a synchronous library. Those. you call the synchronous schedule code from the asynchronous bot, and then from there you will call the asynchronous methods for sending messages? A good way to make life difficult for yourself!
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 секунд если достаточно раз в час?

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question