МУНИЦИПАЛЬНОЕ АВТОНОМНОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ДОПОЛНИТЕЛЬНОГО ОБРАЗОВАНИЯ
«ЦЕНТР ДЕТСКОГО ТЕХНИЧЕСКОГО ТВОРЧЕСТВА»
Методическая разработка
«Создание Telegram-бота с расписанием
для IT-КУБ»
к дополнительной общеобразовательной
общеразвивающей программе
технической направленности
«Программирование на Python»
Возраст детей: 10-17 лет
Автор: Костычев Вадим Александрович
г. Заречный Пензенской области
2025 г.
Данный методический материал предназначен для преподавателей и учащихся, изучающих создание чат-ботов с использованием Python и библиотеки python-telegram-bot. На основе предоставленного кода мы рассмотрим, как реализовать Telegram-бота для отображения расписания занятий IT-КУБ, настройки напоминаний и предоставления информации о курсах. Материал включает описание функционала, структуры кода, инструкции по запуску и идеи для дальнейшего развития.
Цели:
создать telegram-бота, который помогает учащимся, родителям и гостям IT-куб получать актуальное расписание занятий;
обеспечить удобный интерфейс для взаимодействия через текстовые команды и инлайн-кнопки;
научить основам работы с библиотекой python-telegram-bot для создания диалоговых ботов.
Задачи:
реализовать выбор роли пользователя (ученик, родитель, гость);
предоставить возможность выбора учебной группы и просмотра расписания;
добавить функцию настройки уведомлений о занятиях;
выводить информацию о курсах it-куб;
обеспечить логирование для отладки.
Описание функционала бота
Бот предназначен для упрощения доступа к расписанию занятий IT-КУБ. Основные функции:
Команда /start:
Приветствует пользователя и предлагает выбрать роль: ученик, родитель или гость.
Выбор группы:
Показывает список доступных групп (например, "Python Junior", "Робототехника 12+"). Пользователь выбирает группу через инлайн-кнопки.
Главное меню:
Просмотр расписания: выводит дни, время, кабинет и преподавателя для выбранной группы. Настройка напоминаний: позволяет включить уведомления за 24 часа, за 1 час или отключить их. Информация о курсах: показывает описание выбранного курса или всех курсов.
Команда /cancel:
Завершает диалог и возвращает бота в начальное состояние.
Логирование:
Записывает действия пользователя (выбор роли, группы, запрос расписания) для отладки.
Структура кода
Код организован с использованием ConversationHandler для управления диалогом. Основные компоненты:
Библиотеки и настройки
import logging
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import (
Application, CommandHandler, CallbackQueryHandler, ConversationHandler, ContextTypes
)
logging: для записи действий бота в консоль.
telegram: классы для создания сообщений и кнопок.
telegram.ext: инструменты для обработки команд и callback-запросов.
Логирование настраивается для вывода информации о действиях:
logging.basicConfig(
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
)
logger = logging.getLogger(__name__)
Данные
Расписание и информация о курсах хранятся в словарях (в реальном проекте лучше использовать базу данных):
GROUPS = {
"Python Junior": [
{"day": "Понедельник", "time": "17:00-18:30", "room": "204", "teacher": "Иванов А."},
{"day": "Среда", "time": "17:00-18:30", "room": "204", "teacher": "Иванов А."},
],
"Робототехника 12+": [
{"day": "Вторник", "time": "15:00-16:30", "room": "301", "teacher": "Петров В."},
],
}
COURSES = {
"Python Junior": "Курс для подростков 14-16 лет. Изучение Python.",
"Робототехника 12+": "Курс для детей 12+. Робототехника.",
}
user_data = {}
GROUPS: хранит расписание по группам (день, время, кабинет, преподаватель).
COURSES: описания курсов.
user_data: Словарь для хранения данных пользователя (роль, группа, настройки напоминаний).
Состояния диалога
Определены четыре состояния для ConversationHandler:
SELECT_ROLE, SELECT_GROUP, MAIN_MENU, SET_REMINDERS = range(4)
SELECT_ROLE: Выбор роли (ученик, родитель, гость).
SELECT_GROUP: Выбор учебной группы.
MAIN_MENU: Основное меню с функциями.
SET_REMINDERS: Настройка уведомлений.
Обработчики
start: Обрабатывает команду /start, показывает кнопки выбора роли.
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
logger.info(f"User {update.effective_user.id} started the bot")
keyboard = [
[InlineKeyboardButton("Ученик", callback_data="role_student")],
[InlineKeyboardButton("Родитель", callback_data="role_parent")],
[InlineKeyboardButton("Гость", callback_data="role_guest")],
]
reply_markup = InlineKeyboardMarkup(keyboard)
await update.message.reply_text(
"Привет! 👋 Я бот IT-КУБ. Кто ты?", reply_markup=reply_markup
)
return SELECT_ROLE
select_role: сохраняет выбранную роль и предлагает выбрать группу;
select_group: сохраняет группу и открывает главное меню;
show_schedule: показывает расписание выбранной группы;
set_reminders и remind_choice: настраивают уведомления;
about_courses: выводит информацию о курсах;
back_to_menu: возвращает в главное меню;
cancel: завершает диалог.
ConversationHandler
Управляет диалогом:
conv_handler = ConversationHandler(
entry_points=[CommandHandler("start", start)],
states={
SELECT_ROLE: [CallbackQueryHandler(select_role, pattern="^role_")],
SELECT_GROUP: [CallbackQueryHandler(select_group, pattern="^group_")],
MAIN_MENU: [
CallbackQueryHandler(show_schedule, pattern="^show_schedule$"),
CallbackQueryHandler(set_reminders, pattern="^set_reminders$"),
CallbackQueryHandler(about_courses, pattern="^about_courses$"),
CallbackQueryHandler(back_to_menu, pattern="^back_to_menu$"),
],
SET_REMINDERS: [
CallbackQueryHandler(remind_choice, pattern="^remind_"),
CallbackQueryHandler(back_to_menu, pattern="^back_to_menu$"),
],
},
fallbacks=[CommandHandler("cancel", cancel)],
)
Пример взаимодействия с ботом
Пользователь отправляет /start:
Привет! 👋 Я бот IT-КУБ. Кто ты?
[Кнопки: Ученик, Родитель, Гость]
Выбирает "Ученик":
Выбери группу:
[Кнопки: Python Junior, Робототехника 12+]
Выбирает "Python Junior":
Группа: Python Junior. Что дальше?
[Кнопки: Расписание, Напоминания, О курсах]
Нажимает "Расписание":
📅 Расписание для Python Junior:
Понедельник: 17:00-18:30 (каб. 204, Иванов А.)
Среда: 17:00-18:30 (каб. 204, Иванов А.)
[Кнопка: Назад]
Нажимает "Напоминания":
Когда напоминать?
[Кнопки: За 24 часа, За 1 час, Отключить, Назад]
Выбирает "За 1 час":
Напоминания за 1 час включены!
[Кнопка: Назад]
Отправляет /cancel:
До встречи! 👋
Анализ кода
Преимущества
Простота: Используется ConversationHandler для четкого управления диалогом.
Модульность: Функции разбиты по задачам (выбор роли, группы, расписание).
Логирование: Помогает отслеживать действия и находить ошибки.
Инлайн-кнопки: Удобный интерфейс для пользователей.
Ограничения
Хранение данных: Расписание и курсы хранятся в коде. Для реального проекта нужна база данных (SQLite, PostgreSQL) или Google Таблицы.
Напоминания: Пока только сохраняют выбор (24 часа/1 час). Для реальных уведомлений нужен JobQueue и парсинг времени.
Авторизация: Нет проверки, кто является учеником или родителем.
Масштабируемость: Для большого количества групп и пользователей словарь user_data неэффективен.
Листинг программного кода
import logging
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import (
Application,
CommandHandler,
CallbackQueryHandler,
ConversationHandler,
ContextTypes,
)
# Настройка логирования
logging.basicConfig(
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
)
logger = logging.getLogger(__name__)
# Состояния
SELECT_ROLE, SELECT_GROUP, MAIN_MENU, SET_REMINDERS = range(4)
# Данные
GROUPS = {
"Python Junior": [
{"day": "Понедельник", "time": "17:00-18:30", "room": "204", "teacher": "Иванов А."},
{"day": "Среда", "time": "17:00-18:30", "room": "204", "teacher": "Иванов А."},
],
"Робототехника 12+": [
{"day": "Вторник", "time": "15:00-16:30", "room": "301", "teacher": "Петров В."},
],
}
COURSES = {
"Python Junior": "Курс для подростков 14-16 лет. Изучение Python.",
"Робототехника 12+": "Курс для детей 12+. Робототехника.",
}
user_data = {}
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
logger.info(f"User {update.effective_user.id} started the bot")
keyboard = [
[InlineKeyboardButton("Ученик", callback_data="role_student")],
[InlineKeyboardButton("Родитель", callback_data="role_parent")],
[InlineKeyboardButton("Гость", callback_data="role_guest")],
]
reply_markup = InlineKeyboardMarkup(keyboard)
await update.message.reply_text(
"Привет! 👋 Я бот IT-КУБ. Кто ты?", reply_markup=reply_markup
)
return SELECT_ROLE
async def select_role(update: Update, context: ContextTypes.DEFAULT_TYPE):
query = update.callback_query
await query.answer()
logger.info(f"User {query.from_user.id} selected role: {query.data}")
user_data[query.from_user.id] = {"role": query.data}
keyboard = [[InlineKeyboardButton(name, callback_data=f"group_{name}")] for name in GROUPS.keys()]
reply_markup = InlineKeyboardMarkup(keyboard)
await query.message.edit_text("Выбери группу:", reply_markup=reply_markup)
return SELECT_GROUP
async def select_group(update: Update, context: ContextTypes.DEFAULT_TYPE):
query = update.callback_query
await query.answer()
group = query.data.split("_")[1]
user_data[query.from_user.id]["group"] = group
logger.info(f"User {query.from_user.id} selected group: {group}")
keyboard = [
[InlineKeyboardButton("Расписание", callback_data="show_schedule")],
[InlineKeyboardButton("Напоминания", callback_data="set_reminders")],
[InlineKeyboardButton("О курсах", callback_data="about_courses")],
]
reply_markup = InlineKeyboardMarkup(keyboard)
await query.message.edit_text(f"Группа: {group}. Что дальше?", reply_markup=reply_markup)
return MAIN_MENU
async def show_schedule(update: Update, context: ContextTypes.DEFAULT_TYPE):
query = update.callback_query
await query.answer()
user_id = query.from_user.id
group = user_data.get(user_id, {}).get("group")
logger.info(f"User {user_id} requested schedule for group: {group}")
if not group or group not in GROUPS:
await query.message.edit_text("Выбери группу сначала.")
return MAIN_MENU
schedule_text = f"📅 Расписание для {group}:\n\n"
for lesson in GROUPS[group]:
schedule_text += f"{lesson['day']}: {lesson['time']} (каб. {lesson['room']}, {lesson['teacher']})\n"
keyboard = [[InlineKeyboardButton("Назад", callback_data="back_to_menu")]]
reply_markup = InlineKeyboardMarkup(keyboard)
await query.message.edit_text(schedule_text, reply_markup=reply_markup)
return MAIN_MENU
async def set_reminders(update: Update, context: ContextTypes.DEFAULT_TYPE):
query = update.callback_query
await query.answer()
logger.info(f"User {query.from_user.id} entered reminders menu")
keyboard = [
[InlineKeyboardButton("За 24 часа", callback_data="remind_24h")],
[InlineKeyboardButton("За 1 час", callback_data="remind_1h")],
[InlineKeyboardButton("Отключить", callback_data="remind_off")],
[InlineKeyboardButton("Назад", callback_data="back_to_menu")],
]
reply_markup = InlineKeyboardMarkup(keyboard)
await query.message.edit_text("Когда напоминать?", reply_markup=reply_markup)
return SET_REMINDERS
async def remind_choice(update: Update, context: ContextTypes.DEFAULT_TYPE):
query = update.callback_query
await query.answer()
user_id = query.from_user.id
choice = query.data
logger.info(f"User {user_id} chose reminder option: {choice}")
if choice == "remind_24h":
user_data[user_id]["reminders"] = "24h"
text = "Напоминания за 24 часа включены!"
elif choice == "remind_1h":
user_data[user_id]["reminders"] = "1h"
text = "Напоминания за 1 час включены!"
elif choice == "remind_off":
user_data[user_id]["reminders"] = None
text = "Напоминания отключены."
keyboard = [[InlineKeyboardButton("Назад", callback_data="back_to_menu")]]
reply_markup = InlineKeyboardMarkup(keyboard)
await query.message.edit_text(text, reply_markup=reply_markup)
return MAIN_MENU
async def about_courses(update: Update, context: ContextTypes.DEFAULT_TYPE):
query = update.callback_query
await query.answer()
user_id = query.from_user.id
group = user_data.get(user_id, {}).get("group")
logger.info(f"User {user_id} requested course info for group: {group}")
text = f"О курсе {group}:\n\n{COURSES[group]}" if group in COURSES else "Информация о курсах:\n\n" + "\n".join(
[f"{k}: {v}" for k, v in COURSES.items()]
)
keyboard = [[InlineKeyboardButton("Назад", callback_data="back_to_menu")]]
reply_markup = InlineKeyboardMarkup(keyboard)
await query.message.edit_text(text, reply_markup=reply_markup)
return MAIN_MENU
async def back_to_menu(update: Update, context: ContextTypes.DEFAULT_TYPE):
query = update.callback_query
await query.answer()
user_id = query.from_user.id
group = user_data.get(user_id, {}).get("group", "не выбрана")
logger.info(f"User {user_id} returned to main menu")
keyboard = [
[InlineKeyboardButton("Расписание", callback_data="show_schedule")],
[InlineKeyboardButton("Напоминания", callback_data="set_reminders")],
[InlineKeyboardButton("О курсах", callback_data="about_courses")],
]
reply_markup = InlineKeyboardMarkup(keyboard)
await query.message.edit_text(f"Группа: {group}. Что дальше?", reply_markup=reply_markup)
return MAIN_MENU
async def cancel(update: Update, context: ContextTypes.DEFAULT_TYPE):
logger.info(f"User {update.effective_user.id} cancelled")
await update.message.reply_text("До встречи! 👋")
return ConversationHandler.END
def main():
# Замените 'YOUR_BOT_TOKEN' на реальный токен
application = Application.builder().token('YOUR_BOT_TOKEN').build()
conv_handler = ConversationHandler(
entry_points=[CommandHandler("start", start)],
states={
SELECT_ROLE: [CallbackQueryHandler(select_role, pattern="^role_")],
SELECT_GROUP: [CallbackQueryHandler(select_group, pattern="^group_")],
MAIN_MENU: [
CallbackQueryHandler(show_schedule, pattern="^show_schedule$"),
CallbackQueryHandler(set_reminders, pattern="^set_reminders$"),
CallbackQueryHandler(about_courses, pattern="^about_courses$"),
CallbackQueryHandler(back_to_menu, pattern="^back_to_menu$"),
],
SET_REMINDERS: [
CallbackQueryHandler(remind_choice, pattern="^remind_"),
CallbackQueryHandler(back_to_menu, pattern="^back_to_menu$"),
],
},
fallbacks=[CommandHandler("cancel", cancel)],
)
application.add_handler(conv_handler)
logger.info("Bot started polling")
application.run_polling(allowed_updates=Update.ALL_TYPES)
if __name__ == "__main__":
main()
Бот IT-Cube— это пример простого, но функционального решения для образовательной среды IT-КУБ. Он демонстрирует базовые принципы создания чат-ботов, включая обработку команд, инлайн-кнопки и управление диалогом. Код можно расширить для поддержки базы данных, сложных уведомлений и интеграций, что делает его отличной основой для учебных проектов.