- PVSM.RU - https://www.pvsm.ru -
Всем привет!
Если на работе я — инженер-проектировщик, то дома я — садовод-огородник, и при большом количестве разных зеленых друзей на подоконнике — теряешься в расписании полива. Поэтому я решила написать бота для растений — мы напишем простого, но полезного помощника: Telegram-бота, который будет напоминать, когда поливать цветы.
В этой части мы реализуем диалоговую логику. А во второй части — подключим базу данных и настроим уведомления.
К концу первой части у вас будет бот, который:
здоровается по имени
принимает команду /add_plant
ведёт диалог: «Как зовут растение? Когда поливал(а)? Через сколько дней снова?»
Что нам понадобится?
|
Что |
Для чего |
|
Telegram |
Где будет жить бот |
|
Python 3.12+ |
Язык программирования |
|
Любой текстовый редактор (Блокнот, VS Code) |
Чтобы писать код |
Telegram → @BotFather [1] → Start → Список команд
Нажимаем /newbot. Выбираем имя и username.
Важно про username!
Должен оканчиваться на bot (можно _bot, Bot, BOT — регистр не важен)
Только латинские буквы, цифры и подчёркивания
Максимум 32 символа
Должен быть уникальным во всём Telegram
Получаем токен и прячем его. (Токен мы никому не передаем, не выкладываем на Git (вообще не выкладываем в интернет)).
Если всё прошло успешно, BotFather отправит:
Опционально, но очень рекомендуется: настраиваем «личность» бота
После создания бота BotFather предложит команды для настройки. Я хочу чтобы бот выглядел красиво и был настоящим помощником.

Я же заполнила описание, поставила аватарку. Теперь вот выглядит миленько.
Переходим в наш бот, нажимаем /start и видим, что бот неактивен, а теперь займемся его оживлением.
Переходим в cmd и вводим python --version. Если выдает ошибку - то нам нужно сначала скачать и установить Python себе на компьютер.
Выбираем актуальную версию с официального сайта https://www.python.org/downloads/windows/ [2] , скачиваем и устанавливаем.
ВАЖНО! На первом экране установки поставьте галочку:
✅ Add Python to PATH (Это позволит запускать python из командной строки)
Возвращаемся в cmd вводим python --version и должны получить версию (может быть другая)
И надо не забыть установить библиотеку python-telegram-botpip install python-telegram-bot
Команда должна (и обязана) совершиться без ошибки.
As for me, самая тяжелая часть.
Создаем папку проекта, где будут храниться файлы нашего бота. Создать внутри папки файл, например, bot.py. В файле bot.py пишем код:
Подробнее про использование используемых библиотек, все четко и по делу - https://docs-python.ru/packages/biblioteka-python-telegram-bot-python/ [3]
#Импортируем нужные инструменты из библиотеки python-telegram-bot, в данном случае это Update:
from telegram import Update
from telegram.ext import Application, CommandHandler, ContextTypes
#СЮДА ВСТАВЛЯЕТСЯ ТОКЕН, КОТОРЫЙ ВЫДАЛ
#никогда никому не показывайте этот токен ! (тот, который ниже - ненастоящий)
BOT_TOKEN = "876543234567898765432"
#функция, которая срабатывает, когда пользователь пишет /start
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
#достаём информацию о пользователе
effective_user — это объект, содержащий: имя, ID, username и т.д. (берём имя из профиля Telegram)
user = update.effective_user
name = user.first_name or "друг"
#Если имя не указано - то напишем друг)
#отправляем ответное сообщение прямо в чат с пользователем
await update.message.reply_text(
f"Привет, {name}! 🌸n"
"Я — бот для ухода за цветами.n"
"Рада тебя видеть!"
)
#Функция, которая запускает бота
def main():
app = Application.builder().token(BOT_TOKEN).build()
#говорим боту: «Когда кто-то напишет /start — вызови функцию start»
app.add_handler(CommandHandler("start", start))
#это сообщение выводится в терминале (чисто прикормка для тревожника,
#чтобы мы знали что код отработал без ошибок и не зациклился)
print("Бот запущен! Напиши ему в Telegram.")
#запускаем цикл - бот сидит и ждет новых сообщений
run_polling()
app.run_polling()
#эта строчка стандартная «заглушка»
if name == "main":
main()
Сохраняем файл, переходим в cmd и вводим C:Usersadminflower_bot>python bot.py [4]
Переходим в Telegram и отправляем /start

Структура кода будет такая:
Пользователь: /add_plant
↓
Бот: → вызывает ask_name (entry_point)
↓
Пользователь: "Фикус"
↓
Бот: сохраняет 'Фикус' → спрашивает дату → переходит в состояние DATE
↓
Пользователь: "15.11.2025"
↓
Бот: сохраняет дату → спрашивает интервал → переходит в INTERVAL
↓
Пользователь: "7"
↓
Бот: выводит сводку → очищает данные → завершает диалог
Нам нужно добавить новые функции, чтобы бот "разговаривал" с нами
Спрашиваем название растения: ask_name
Назначение: Получить и сохранить название растения от пользователя. Вызывается после команды /add_plant.
Что делает:
• Берёт текст сообщения (название растения) из update.message.text.
• Сохраняет его во вр��менное хранилище пользователя context.user_data['name'].
• Отправляет сообщение с запросом даты.
• Возвращает состояние DATE → бот "переключается" на следующий шаг диалога. async def ask_name(update, context): context.user_data['name'] = update.message.text # ← записываем в "блокнот" пользователя
await update.message.reply_text("📅 Дата последнего полива?")
return DATE # → переходим к шагу DATE
Спрашиваем дату последнего полива: ask_date
Назначение: Получить и сохранить дату последнего полива.
Вызывается когда бот находится в состоянии DATE (после ask_name). Что делает:
• Берёт текст сообщения (дату) без валидации
• Сохраняет в context.user_data['date'].
• Запрашивает интервал полива.
• Возвращает состояние INTERVAL → переход к финальному шагу. async def ask_date(update, context): context.user_data['date'] = update.message.text ← сохраняем дату как строку await update.message.reply_text("⏳ Интервал полива (дней)?") return INTERVAL → переходим к шагу INTERVAL
Спрашиваем интервал полива: ask_interval
Назначение: Получить интервал и завершить диалог, показав сводку.
Вызывается, когда бот состоянии INTERVAL (после ask_date).
Что делает:
• Извлекает все данные из "блокнота": name, date, и текущее сообщение — интервал.
• Формирует и отправляет итоговое сообщение с подтверждением.
• Очищает user_data
• Возвращает ConversationHandler.END — диалог закрывается. async def ask_interval(update, context):
Берём всё, что накопили:
name = context.user_data['name'] # название date = context.user_data['date'] # дата interval = update.message.text # интервал
Подтверждаем добавление:await update.message.reply_text(
f"✅ {name} добавлено!n"
f"Последний полив: {date}n"
f"Интервал: {interval} дней"
)
В итоге у нас получается такой код:
from telegram import Update
from telegram.ext import (
Application,
CommandHandler,
MessageHandler,
filters,
ContextTypes,
ConversationHandler,
)
# ТОКЕН!
BOT_TOKEN = "838765567890-098765456789098765"
# Этапы диалога (состояния ConversationHandler)
# Используем константы для читаемости: 0 → NAME, 1 → DATE, 2 → INTERVAL
NAME, DATE, INTERVAL = range(3)
# === /start — приветствие и инструкция ===
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
await update.message.reply_text(
"Привет! 🌿n Чтобы добавить растение — отправь /add_plant"
)
# === /add_plant — запуск диалога ===
async def add_plant_start(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""
Бот переходит в состояние NAME - ожидаем название растения.
"""
await update.message.reply_text("🌿 Название растения?")
return NAME # → переключаемся на этап NAME
# === Этап NAME: получаем и проверяем название ===
async def ask_name(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""
Обрабатывает ввод названия растения.
- Проверяем, что строка не пустая (минимальная валидация).
- Сохраняем в user_data — временный контекст пользователя.
- Переходим к следующему этапу — DATE.
"""
plant_name = update.message.text.strip()
if not plant_name:
await update.message.reply_text("❌ Введи название.")
return NAME # остаёмся на том же этапе (повторный запрос)
context.user_data['plant_name'] = plant_name # ← сохраняем в "блокнот"
await update.message.reply_text("📅 Дата последнего полива (ДД.ММ.ГГГГ)?")
return DATE # → переходим к этапу DATE
# === Этап DATE: парсим дату ===
async def ask_date(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""
Ожидаем дату в строгом формате ДД.ММ.ГГГГ.
- Используем datetime.strptime — защита от некорректного ввода.
- При ошибке — просим повторить, не выходя из состояния.
- Сохраняем в ISO-формате (YYYY-MM-DD)
"""
try:
from datetime import datetime
# Парсим дату по шаблону — строгая валидация
last_watered = datetime.strptime(update.message.text.strip(), "%d.%m.%Y").date()
# Сохраняем как строку в формате ISO (2025-11-19) — стандарт для хранения
context.user_data['last_watered'] = last_watered.isoformat()
await update.message.reply_text("⏳ Интервал полива (дней)?")
return INTERVAL # → переходим к финальному этапу
except ValueError:
# Если формат неверный — не прерываем диалог, а просим исправить
await update.message.reply_text("❌ Формат: ДД.ММ.ГГГГ")
return DATE # остаёмся в состоянии DATE
# === Этап INTERVAL: проверяем и завершаем ===
async def ask_interval(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""
Получаем интервал полива.
- Проверяем, что это целое положительное число.
- Формируем итоговое сообщение.
- Очищаем user_data — хорошая практика (избегаем "утечек" между сессиями).
- Завершаем диалог.
"""
try:
interval = int(update.message.text.strip())
if interval <= 0:
raise ValueError # чтобы обработать как ошибку ввода
# Достаём ранее сохранённые данные
plant_name = context.user_data['plant_name']
last_watered = context.user_data['last_watered']
# Подтверждаем добавление (в реальном проекте — здесь вызов БД)
await update.message.reply_text(
f"✅ {plant_name} добавлено!n"
f"Последний полив: {last_watered}n"
f"Интервал: {interval} дней"
)
# Чистим временные данные
context.user_data.clear()
return ConversationHandler.END # ← диалог завершён
except ValueError:
await update.message.reply_text("❌ Введи целое число > 0.")
return INTERVAL # повторный запрос, не выходя из состояния
# === Основная функция: сборка и запуск бота ===
def main():
"""Собирает приложение и регистрирует обработчики."""
app = Application.builder().token(BOT_TOKEN).build()
# Диалоговый обработчик: управляет состояниями и переходами
conv_handler = ConversationHandler(
# Диалог начинается с команды /add_plant
entry_points=[CommandHandler("add_plant", add_plant_start)],
# Что происходит на каждом этапе
states={
NAME: [MessageHandler(filters.TEXT & ~filters.COMMAND, ask_name)],
DATE: [MessageHandler(filters.TEXT & ~filters.COMMAND, ask_date)],
INTERVAL: [MessageHandler(filters.TEXT & ~filters.COMMAND, ask_interval)],
},
# Диалог изолирован по пользователям (по умолчанию True)
per_user=True,
)
# Регистрируем обработчики команд и диалогов
app.add_handler(CommandHandler("start", start))
app.add_handler(conv_handler)
print("✅ Бот с диалогом запущен!")
app.run_polling()
if __name__ == "__main__":
main()
Переходим в Телеграмм и начинаем общаться с нашим ботом
В этой статье мы собрали «скелет» Telegram-бота: от регистрации в BotFather до рабочего диалогового интерфейса. Реализовали пошаговое добавление растения.
Мы реализовали пошаговое добавление растения через ConversationHandler: бот последовательно запрашивает название, дату последнего полива и интервал, сохраняя промежуточные данные в context.user_data.
Что дальше?
Во второй части мы:
подключим базу данных, чтобы данные не исчезали после перезапуска;
добавим команду /list — чтобы пользователь видел все свои растения;
и настроим напоминания о поливе через JobQueue
Автор: kimd_me
Источник [5]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/python/437530
Ссылки в тексте:
[1] @BotFather: https://www.pvsm.ru/users/BotFather
[2] https://www.python.org/downloads/windows/: https://www.python.org/downloads/windows/
[3] https://docs-python.ru/packages/biblioteka-python-telegram-bot-python/: https://docs-python.ru/packages/biblioteka-python-telegram-bot-python/
[4] bot.py: http://bot.py
[5] Источник: https://habr.com/ru/articles/969448/?utm_source=habrahabr&utm_medium=rss&utm_campaign=969448
Нажмите здесь для печати.