TGViewer
CodeShadow CodeShadow @codeshadowcources · 77 subscribers
Post #360 57
🚀 Telegram-бот — Часть 2: Хелперы и планировщик напоминаний

➡️ПЕРВЫЙ ПОСТ ПО ПРОЕКТУ
➡️ЧАСТЬ 1
Привет, кодеры! Продолжаем разбор Telegram-бота для планирования задач. В первом посте — обзор, в Части 1 — БД и модели. Сегодня: utils.py (хелперы) и scheduler.py (напоминания с APScheduler).


🗂 Хелперы: utils.py

Утилиты для парсинга дат, форматирования и клавиатур Telegram.

# utils.py (ключевые функции)
from datetime import datetime
from dateutil import parser
from config import TZ
from telebot import types

def parse_datetime_user(text: str) -> datetime:
formats = ["%Y-%m-%d %H:%M", "%d.%m.%Y %H:%M", "%Y-%m-%d", "%d.%m.%Y"]
for fmt in formats:
try:
dt = datetime.strptime(text, fmt)
return TZ.localize(dt)
except ValueError:
continue
return None

def format_task(task):
s = f"#{task.id} {task.title}\nКогда: {task.starts_at.strftime('%Y-%m-%d %H:%M')}\nСтатус: {task.status.value}"
if task.description:
s += f"\n{task.description}"
return s

def make_main_keyboard():
kb = types.ReplyKeyboardMarkup(resize_keyboard=True)
kb.row(types.KeyboardButton("➕ Добавить задачу"), types.KeyboardButton("➕ Добавить пару (фикс.)"))
kb.row(types.KeyboardButton("📋 Мои задачи"), types.KeyboardButton("📅 Расписание / Календарь"))
kb.row(types.KeyboardButton("⚙️ Настройки"), types.KeyboardButton("📝 Отчёт за неделю"))
return kb

- parse_datetime_user: парсит даты в разных форматах, добавляет таймзону.
- format_task: выводит задачу в читаемом виде.
- make_main_keyboard: главная клавиатура с кнопками.

🗂 Планировщик: scheduler.py

Фоновая система напоминаний на APScheduler.

# scheduler.py (основные функции)
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.triggers.date import DateTrigger
from apscheduler.triggers.cron import CronTrigger
from db import SessionLocal
from models import Task, ClassSchedule, User, TaskStatus
from config import TZ

scheduler = BackgroundScheduler(timezone=TZ)
scheduler.start()

def schedule_task_reminder(task_id: int, when: datetime, bot, message_text: str):
job_id = f"task_{task_id}"
scheduler.add_job(
func=lambda: _send_task_reminder(task_id, bot, message_text),
trigger=DateTrigger(run_date=when),
id=job_id,
replace_existing=True
)

# _send_task_reminder: отправляет сообщение, если задача pending
def schedule_weekly_class_reminder(class_id: int, bot):
# Настраивает cron для еженедельного напоминания по дню/времени
# Использует remind_before_minutes или дефолт 30 мин
pass # (полный код в репозитории)

def load_all_jobs(bot):
# При старте загружает все pending задачи и active классы в scheduler
pass

- schedule_task_reminder: разовое напоминание за N минут до задачи.
- schedule_weekly_class_reminder: еженедельные cron-задачи для занятий.
- load_all_jobs: восстанавливает задания при запуске бота.


🔧 Советы:
- APScheduler в памяти; для продакшена — job store в БД.
- Проверяйте статус перед отправкой, чтобы избежать спама.
- Логируйте ошибки отправки.


В следующем посте — bot_handlers.py: обработчики команд и FSM для диалогов. Вопросы по APScheduler? Пиши!

🧠 Что добавить в напоминания? Идеи в комментах!


#CodeShadow #TelegramBot #Python #APScheduler #Планировщик
More from @codeshadowcources
  1. Oct 9, 2026🖥
  2. Oct 8, 2026Наш внутренний проект для преподавателей. Думаю, получилось отлично)
  3. Oct 8, 2026🎮 Как мы внедрили геймификацию в работу преподавателей Геймификация давно вышла за предел…
  4. Oct 6, 2026😎
  5. Oct 3, 2026😐
  6. Sep 27, 2026Пусть Codex или Claude сами напишут MCP Теперь кейс посерьёзнее. Допустим, приходит клиент…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →