Files
tg_bot_language/bot/handlers/reminder.py
mamonov.ep 72a63eeda5 Добавлены основные функции MVP: тематические подборки, импорт слов, диалоговая практика, напоминания и тест уровня
Новые команды:
- /words [тема] - AI-генерация тематических подборок слов (10 слов по теме с учётом уровня)
- /import - извлечение до 15 ключевых слов из текста (книги, статьи, песни)
- /practice - диалоговая практика с AI в 6 сценариях (ресторан, магазин, путешествие, работа, врач, общение)
- /reminder - настройка ежедневных напоминаний по расписанию
- /level_test - тест из 7 вопросов для определения уровня английского (A1-C2)

Основные изменения:
- AI сервис: добавлены методы generate_thematic_words, extract_words_from_text, start_conversation, continue_conversation, generate_level_test
- Диалоговая практика: исправление ошибок в реальном времени, подсказки, перевод реплик
- Напоминания: APScheduler для ежедневной отправки напоминаний в выбранное время
- Тест уровня: автоматическое определение уровня при регистрации, можно пропустить
- База данных: добавлены поля reminders_enabled, last_reminder_sent
- Vocabulary service: метод get_word_by_original для проверки дубликатов
- Зависимости: apscheduler==3.10.4

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 15:46:02 +03:00

173 lines
6.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from aiogram import Router, F
from aiogram.filters import Command
from aiogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
from database.db import async_session_maker
from services.user_service import UserService
router = Router()
class ReminderStates(StatesGroup):
"""Состояния для настройки напоминаний"""
waiting_for_time = State()
@router.message(Command("reminder"))
async def cmd_reminder(message: Message):
"""Обработчик команды /reminder"""
async with async_session_maker() as session:
user = await UserService.get_user_by_telegram_id(session, message.from_user.id)
if not user:
await message.answer("Сначала запусти бота командой /start")
return
# Формируем текст
status = "✅ Включены" if user.reminders_enabled else "❌ Выключены"
time_text = user.daily_task_time if user.daily_task_time else "Не установлено"
text = (
f"⏰ <b>Напоминания</b>\n\n"
f"Статус: {status}\n"
f"Время: {time_text} UTC\n\n"
f"Напоминания помогут не забывать о ежедневной практике.\n"
f"Бот будет присылать сообщение в выбранное время каждый день."
)
# Создаем кнопки
keyboard = []
if user.reminders_enabled:
keyboard.append([
InlineKeyboardButton(text="❌ Выключить", callback_data="reminder_disable")
])
else:
keyboard.append([
InlineKeyboardButton(text="✅ Включить", callback_data="reminder_enable")
])
keyboard.append([
InlineKeyboardButton(text="⏰ Изменить время", callback_data="reminder_set_time")
])
reply_markup = InlineKeyboardMarkup(inline_keyboard=keyboard)
await message.answer(text, reply_markup=reply_markup)
@router.callback_query(F.data == "reminder_enable")
async def enable_reminders(callback: CallbackQuery):
"""Включить напоминания"""
async with async_session_maker() as session:
user = await UserService.get_user_by_telegram_id(session, callback.from_user.id)
if not user.daily_task_time:
await callback.answer(
"Сначала установи время напоминаний!",
show_alert=True
)
return
user.reminders_enabled = True
await session.commit()
await callback.answer("✅ Напоминания включены!")
await callback.message.edit_text(
f"✅ <b>Напоминания включены!</b>\n\n"
f"Время: {user.daily_task_time} UTC\n\n"
f"Ты будешь получать ежедневные напоминания о практике."
)
@router.callback_query(F.data == "reminder_disable")
async def disable_reminders(callback: CallbackQuery):
"""Выключить напоминания"""
async with async_session_maker() as session:
user = await UserService.get_user_by_telegram_id(session, callback.from_user.id)
user.reminders_enabled = False
await session.commit()
await callback.answer("❌ Напоминания выключены")
await callback.message.edit_text(
"❌ <b>Напоминания выключены</b>\n\n"
"Используй /reminder чтобы включить их снова."
)
@router.callback_query(F.data == "reminder_set_time")
async def set_reminder_time_prompt(callback: CallbackQuery, state: FSMContext):
"""Запросить время для напоминаний"""
await state.set_state(ReminderStates.waiting_for_time)
await callback.message.edit_text(
"⏰ <b>Установка времени напоминаний</b>\n\n"
"Отправь время в формате <b>HH:MM</b> (UTC)\n\n"
"Примеры:\n"
"• <code>09:00</code> - 9 утра по UTC\n"
"• <code>18:30</code> - 18:30 по UTC\n"
"• <code>20:00</code> - 8 вечера по UTC\n\n"
"💡 UTC = МСК - 3 часа\n"
"(если хочешь 12:00 по МСК, введи 09:00)\n\n"
"Отправь /cancel для отмены"
)
await callback.answer()
@router.message(Command("cancel"), ReminderStates.waiting_for_time)
async def cancel_set_time(message: Message, state: FSMContext):
"""Отменить установку времени"""
await state.clear()
await message.answer("❌ Установка времени отменена")
@router.message(ReminderStates.waiting_for_time)
async def process_reminder_time(message: Message, state: FSMContext):
"""Обработать введённое время"""
time_str = message.text.strip()
# Валидация формата HH:MM
try:
parts = time_str.split(':')
if len(parts) != 2:
raise ValueError()
hour, minute = int(parts[0]), int(parts[1])
if not (0 <= hour <= 23 and 0 <= minute <= 59):
raise ValueError()
# Формат OK
formatted_time = f"{hour:02d}:{minute:02d}"
except:
await message.answer(
"❌ Неверный формат времени!\n\n"
"Используй формат <b>HH:MM</b> (например, 09:00 или 18:30)\n"
"Или отправь /cancel для отмены"
)
return
# Сохраняем время
async with async_session_maker() as session:
user = await UserService.get_user_by_telegram_id(session, message.from_user.id)
user.daily_task_time = formatted_time
# Автоматически включаем напоминания
user.reminders_enabled = True
await session.commit()
await state.clear()
await message.answer(
f"✅ <b>Время установлено!</b>\n\n"
f"Напоминания: <b>{formatted_time} UTC</b>\n"
f"Статус: <b>Включены</b>\n\n"
f"Ты будешь получать ежедневные напоминания о практике.\n"
f"Используй /reminder для изменения настроек."
)