Как задать обратный отсчёт при написании команды?

Как можно изменить этот код, чтобы при отправке команды start_tracker всем пользователям из списка users начинался обратный отсчёт, а не только тому, кто отправил команду? Я использую библиотеку Aiogram и храню данные в SQLite. Вот мой текущий код:

```python
elif 'start_tracker'.lower() in message.text.lower():
    users = [765963392, 6537306686]
    for user in users:
        timer_seconds = int(db.get_time_tracking(user))
        new_message = await bot.send_message(user, f'{timer_seconds}')
        for seconds_left in range(timer_seconds - 1, -1, -1):
            await asyncio.sleep(1)
            db.set_time_tracking(user, seconds_left)
            await new_message.edit_text(f'{seconds_left}')

        await bot.send_message(user, f'Всё!')
```
  • 26 января 2024 г. 7:18
Ответы на вопрос 2
Чтобы всем пользователям из списка `users` начинался обратный отсчёт одновременно после отправки команды `start_tracker`, можно использовать `asyncio.gather()` для запуска асинхронных функций одновременно для каждого пользователя. Сначала нам нужно определить отдельную асинхронную функцию для управления обратным отсчётом каждого пользователя, а затем вызвать эту функцию для каждого пользователя одновременно.

Пример для изменения кода:

```python
import asyncio

async def start_countdown_for_user(user, db, bot):
    timer_seconds = int(db.get_time_tracking(user))
    new_message = await bot.send_message(user, f'{timer_seconds}')
    for seconds_left in range(timer_seconds - 1, -1, -1):
        await asyncio.sleep(1)  # Замените 1 на нужное количество секунд
        db.set_time_tracking(user, seconds_left)
        await new_message.edit_text(f'{seconds_left}')
    await bot.send_message(user, 'Всё!')

async def start_tracker():
    # Список пользователей
    users = [765963392, 6537306686]

    # Создаем список корутин для каждого пользователя
    countdown_tasks = [start_countdown_for_user(user, db, bot) for user in users]

    # Запускаем все корутины одновременно
    await asyncio.gather(*countdown_tasks)

# Вставьте это в соответствующее место обработчика для команды, например:
@dp.message_handler(commands=['start_tracker'])
async def handle_start_tracker_command(message: types.Message):
    # Стартуем таймеры для всех пользователей
    await start_tracker()

# Не забудьте запустить бота с использованием асинхронного исполнения
# Например, так:
# if __name__ == '__main__':
#     executor.start_polling(dp, skip_updates=True)
```

Обратите внимание, что для запуска функций `start_countdown_for_user()` одновременно для каждого пользователя создается список корутин (`countdown_tasks`), который затем передается в функцию `asyncio.gather()`.

Код функции `handle_start_tracker_command()` является обработчиком для вашей команды `/start_tracker` в Aiogram боте.

Не забудьте также корректно настроить работу с базой данных, чтобы функция `db.get_time_tracking(user)` возвращала нужное и актуальное значение количества секунд до конца обратного отсчёта, и функция `db.set_time_tracking(user, seconds_left)` обновляла его в базе данных для каждого пользователя.

Если функции `db.get_time_tracking()` и `db.set_time_tracking()` выполняются асинхронно, использовать их всё так же, но при вызове необходимо ставить `await` перед ними. Например:
```python
timer_seconds = int(await db.get_time_tracking(user))
...
await db.set_time_tracking(user, seconds_left)
```
Программа делает ровно то, что вы ей указали. Берет пользователя, и начинает ему показывать обратный отсчет. Потом берет второго пользователя и делает то же самое. И т.д., пока пользователи не закончатся. 

Если вы хотите чтобы все было одновременно, вам следует одновременно все это запускать. Сначала получше изучите асинхронность, потом напишите асинхронную функцию которая принимает на вход id пользователя, запрашивает его количество секунд и пр. По сути функция должна делать все то, что описано у вас в теле цикла.

И потом можно попробовать запустить это все, например, через asyncio.gather() .

Сразу предупрежу, что если будет много таких пользователей, есть риск схватить временную блокировку от серверов телеги из-за большого количества запросов. Лучше изучите информацию о том, какие есть ограничения по частоте запросов к серверам телеги.
Похожие вопросы