Тема 6 из 6

Бот-напоминалка

Соберём всё вместе — команды, проверку ввода, списки и, главное, само срабатывание напоминаний.

Время и полночь

Пользователь пишет «напомни в 07:00». Если сейчас 23:00, это завтра. Удобно считать время в минутах от полуночи и брать разность по модулю суток:

diff = ((h * 60 + m) - (now_h * 60 + now_m)) % 1440     # 0 … 1439
return diff or 1440                                       # совпадение — через сутки

В Python остаток от деления на положительное число всегда неотрицательный: -30 % 1440 == 1410.

Данные каждого пользователя

Напоминания хранят отдельно для каждого человека — по message.from_user.id:

REMINDERS = {}                                   # id → список (время, текст)
items = REMINDERS.setdefault(message.from_user.id, [])

setdefault возвращает список пользователя, создавая пустой при первом обращении. Для настоящего бота данные кладут в базу (например, SQLite через aiosqlite) — иначе они пропадут при перезапуске.

Фоновые задачи

Обработчик должен ответить сразу. Ожидание до напоминания запускают отдельной задачей:

tasks = set()


async def fire(bot, chat_id, delay, text):
    await asyncio.sleep(delay)
    await bot.send_message(chat_id, "⏰ " + text)


@router.message(Command("in"))
async def remind_in(message: Message, command: CommandObject, bot: Bot):
    task = asyncio.create_task(fire(bot, message.chat.id, delay, text))
    tasks.add(task)                          # держим ссылку, чтобы задачу не удалил сборщик мусора
    task.add_done_callback(tasks.discard)
    await message.answer("Запомнил")
  • asyncio.create_task запускает корутину в фоне и сразу возвращается;
  • пока задача спит, бот обрабатывает другие сообщения — тысячи напоминаний живут одновременно;
  • bot.send_message(chat_id, текст) — бот пишет сам, не в ответ на сообщение. Объект bot aiogram передаст в обработчик, если добавить параметр bot: Bot.

Если await fire(...) написать прямо в обработчике, он «зависнет» до срабатывания напоминания, и пользователь не получит даже «Запомнил».

Для серьёзного расписания (повторы, напоминания после перезапуска) используют библиотеки вроде APScheduler.

Запуск по-настоящему

  1. В Telegram откройте @BotFather, команда /newbot, придумайте имя — получите токен.
  2. Задайте переменную окружения: в PowerShell $env:BOT_TOKEN = "123456:ABC…", в терминале macOS/Linux export BOT_TOKEN=123456:ABC….
  3. Запустите программу и напишите своему боту в Telegram.

Чтобы бот работал круглосуточно, его запускают на сервере (VPS) или в облаке.

Итог

  • время до напоминания — по модулю 1440, совпадение — через сутки;
  • данные — по from_user.id, setdefault;
  • asyncio.create_task для ожидания, bot.send_message для отправки;
  • токен — только из переменной окружения.